为什么System.Boolean占用4个字节?它只存储一个状态,无论是真还是假,它可以存储在比4个字节更少的空间中.
我想提供一个类来管理创建和随后删除临时目录.理想情况下,我希望它可以在using块中使用,以确保无论我们如何离开块,都会再次删除目录:
static void DoSomethingThatNeedsATemporaryDirectory()
{
using (var tempDir = new TemporaryDirectory())
{
// Use the directory here...
File.WriteAllText(Path.Combine(tempDir.Path, "example.txt"), "foo\nbar\nbaz\n");
// ...
if (SomeCondition)
{
return;
}
if (SomethingIsWrong)
{
throw new Exception("This is an example of something going wrong.");
}
}
// Regardless of whether we leave the using block via the return,
// by throwing and exception or just normally dropping out the end,
// the directory gets deleted by TemporaryDirectory.Dispose.
}
Run Code Online (Sandbox Code Playgroud)
创建目录没问题.问题是如何编写Dispose方法.当我们尝试删除目录时,我们可能会失败; 例如,因为我们仍然在其中打开一个文件.但是,如果我们允许传播异常,它可能会掩盖使用块内发生的异常.特别是,如果在使用块内发生异常,则可能是导致我们无法删除目录的异常,但如果我们屏蔽它,则我们丢失了解决问题的最有用信息.
看来我们有四种选择:
例如,如果我有:
typedef enum { year, month, day } field_type;
inline foo operator *(field_type t,int x)
{
return foo(f,x);
}
inline foo operator -(field_type t)
{
return t*-1;
}
int operator /(distance const &d,field_type v)
{
return d.in(v);
}
Run Code Online (Sandbox Code Playgroud)
因为如果我没有定义这样的运算符,它实际上是合法的day*3,它会被翻译成6?
它合法吗?
至少gcc和intel编译器在没有警告的情况下接受这个.
Clearification:
我不想要默认算术运算,我想要自己的返回非整数类型的操作.
在我的构建过程中,我想要包含符合RFC-3161标准的TSA的时间戳.在运行时,代码将验证此时间戳,最好不需要第三方库的帮助.(这是一个.NET应用程序,所以我可以随时使用标准的哈希和非对称加密功能.)
RFC 3161依赖于ASN.1和X.690以及诸如此类的东西,实现起来并不简单,所以至少现在,我正在使用Bouncy Castle来生成TimeStampReq(请求)并解析TimeStampResp(响应).我只是无法弄清楚如何验证响应.
到目前为止,我已经弄清楚如何提取签名本身,公共证书,创建时间戳的时间,以及我发送的消息imprint摘要和nonce(用于构建时验证).我无法弄清楚的是如何将这些数据放在一起以生成散列和签名的数据.
这是我正在做什么以及我想做什么的粗略概念.这是测试代码,所以我采取了一些快捷方式.一旦我得到了有效的东西,我将不得不清理一些事情并以正确的方式完成它们.
// a lot of fully-qualified type names here to make sure it's clear what I'm using
static void WriteTimestampToBuild(){
var dataToTimestamp = Encoding.UTF8.GetBytes("The rain in Spain falls mainly on the plain");
var hashToTimestamp = new System.Security.Cryptography.SHA1Cng().ComputeHash(dataToTimestamp);
var nonce = GetRandomNonce();
var tsr = GetTimestamp(hashToTimestamp, nonce, "http://some.rfc3161-compliant.server");
var tst = tsr.TimeStampToken;
var tsi = tst.TimeStampInfo;
ValidateNonceAndHash(tsi, hashToTimestamp, nonce);
var cms = tst.ToCmsSignedData();
var signer =
cms.GetSignerInfos().GetSigners()
.Cast<Org.BouncyCastle.Cms.SignerInformation>().First();
// TODO: handle multiple signers?
var signature …Run Code Online (Sandbox Code Playgroud) trust bouncycastle digital-signature trusted-timestamp rfc3161
C#3中的Lambda语法使得创建单行匿名方法非常方便.它们比C#2给我们的匿名委托语法有了明显的改进.然而,lambda的便利性带来了诱惑,在我们不一定需要它们提供的函数式编程语义的地方使用它们.
例如,我经常发现我的事件处理程序(或者至少是开始时)设置状态值的简单单行,或调用另一个函数,或者在另一个对象上设置属性等.对于这些,我应该杂乱无章我的类有另一个简单的函数,或者我应该在构造函数中将lambda填充到事件中?
在这种情况下,lambdas有一些明显的缺点:
由于上述原因,这两件事并没有太多困扰我.通过将lambda存储在成员委托中,我可以解决这两个问题,如果它们确实存在问题,但这样就会破坏使用lambdas的目的,以保证类的清晰度.
不过,还有另外两件事我认为可能不那么明显,但可能更有问题.
每个lambda函数在其包含范围内形成一个闭包.这可能意味着由于闭包维护对它们的引用,在构造函数中较早创建的临时对象保持活动的时间比它们需要的时间长得多.现在希望编译器足够聪明,可以从lambda不使用的闭包中排除对象,但我不确定.有人知道吗?
幸运的是,这并不总是一个问题,因为我不经常在我的构造函数中创建临时对象.我可以想象一下我所做的一个场景,而且我不能轻易将它放在lambda之外.
所以我想借鉴其他人的建议和经验,也许是那些具有其他语言经验和函数式编程功能的人.对于这种事情,是否有任何既定的最佳实践?您是否会避免在事件处理程序中使用lambdas,或者在lambda明显超过其封闭范围的其他情况下使用lambdas?如果没有,你会在什么门槛上决定使用真正的函数而不是lambda?上述任何陷阱都会严重咬伤任何人吗?有没有我没想过的陷阱?
考虑以下代码:
from typing import Callable, TypeVar
T = TypeVar('T')
def middle_man(
producer: Callable[[], T],
consumer: Callable[[T], None]
) -> None:
consumer(producer())
middle_man(
lambda: "HELLO",
lambda s: print(s.lower())
)
Run Code Online (Sandbox Code Playgroud)
这段代码可以正常运行,并且可以正常运行,但是,mypy无法推断s第二个lambda 的类型,从而出现错误:
“对象”没有属性“较低”
现在,我唯一的解决方法是强制转换s(可能是更复杂的lambda或类型更复杂的痛苦),或者添加# type: ignore(我宁愿不这样做)。
有更好的解决方法,还是让mypy识别类型的正确方法?
我是否需要保护Thread垃圾收集器中的对象?包含该线程运行的函数的对象怎么样?
考虑一下这个简单的服
class Server{
readonly TcpClient client;
public Server(TcpClient client){this.client = client;}
public void Serve(){
var stream = client.GetStream();
var writer = new StreamWriter(stream);
var reader = new StreamReader(stream);
writer.AutoFlush = true;
writer.WriteLine("Hello");
while(true){
var input = reader.ReadLine();
if(input.Trim() == "Goodbye")
break;
writer.WriteLine(input.ToUpper());
}
client.Close();
}
}
static void Main(string[] args){
var listener = new TcpListener(IPAddress.Any, int.Parse(args[0]));
listener.Start();
while(true){
var client = listener.AcceptTcpClient();
var server = new Server(client);
var thread = new Thread(server.Serve);
thread.Start();
}
}
Run Code Online (Sandbox Code Playgroud)
我应该将我的线程对象包装在某种静态集合中,以防止它们被垃圾收集器扫除吗?
据推测,如果 …
考虑具有以下签名的库函数:
from typing import Iterator
def get_numbers() -> Iterator[int]:
...
Run Code Online (Sandbox Code Playgroud)
让我们看一些使用它的简单代码:
for i in get_numbers():
print(i)
Run Code Online (Sandbox Code Playgroud)
到目前为止,没有什么有趣的。但是,假设我们不在乎偶数。只有奇数,例如我们:
for i in get_numbers():
if i & 1 == 0:
raise ValueError("Ew, an even number!")
print(i)
Run Code Online (Sandbox Code Playgroud)
现在让我们尝试以下实现get_numbers:
def get_numbers() -> Iterator[int]:
yield 1
yield 2
yield 3
Run Code Online (Sandbox Code Playgroud)
这里没什么有趣的。运行我们的小程序的结果几乎for是我们期望的:
>>> for i in get_numbers():
2 if i & 1 == 0:
3 raise ValueError("Ew, an even number!")
4 print(i)
1
Traceback (most recent call last):
File "<stdin>", line 3, in …Run Code Online (Sandbox Code Playgroud) 我想在会话之间保持pidl,以便我的应用程序可以记住用户的文件夹选择,无论它们在命名空间中的哪个位置,即使它们不是文件系统文件夹.
我有一种感觉,这样做的方法是写出自己的二进制内容ITEMIDLIST,但我无法确认这一点,因为这些内容应该是不透明的,并且取决于提供者.我不知道重启后,甚至在另一个进程中,如果此数据有效.它可以包含指针,就我所知.
什么是坚持并随后重建pidl的正确方法?
Jerry Coffin 提出了一对似乎完全符合我要求的功能.然而,一个问题仍然存在.
正如Joel Spolsky所指出的那样,Raymond Chen 似乎暗示保存二进制内容ITEMIDLIST确实是持久化pidl的正确方法,人们可以从中推断出这一点ILSaveToStream并且ILLoadFromStream正是这样做的辅助函数.
但是,我无法找到证明这一点的文档.由于这个项目是在C#中,我宁愿避免必须IStream为IL...函数进行互操作,如果可能的话我自己只保留二进制数据.任何人都可以确认这是正确的吗?
查看ILSaveToStream和ILLoadFromStream的文档,我发现这些函数在shell 5.0版本之前甚至都不存在(Windows 2000).那么在Win2K之前如何完成呢?经过一些测试,我得出的结论是,正如我所怀疑和Joel Spolsky所假设的那样,写下原始文件ITEMIDLIST是要走的路.
C#中的一个简单实现如下:
unsafe{
byte* start = (byte*)pidl.ToPointer();
byte* ptr = start;
ushort* length;
do{
length = (ushort*)ptr;
ptr += *length;
}while(*length != 0);
byte[] rtn = new byte[ptr + 2 - start];
Marshal.Copy(pidl, rtn, 0, rtn.Length);
return rtn;
}
Run Code Online (Sandbox Code Playgroud)
当然,这可以在没有使用指针的情况下完成 …
你能发现下面代码中的错误吗?米皮不能。
from typing import Dict, Any
def add_items(d: Dict[str, Any]) -> None:
d['foo'] = 5
d: Dict[str, str] = {}
add_items(d)
for key, value in d.items():
print(f"{repr(key)}: {repr(value.lower())}")
Run Code Online (Sandbox Code Playgroud)
当然,Python 发现了错误,这有助于通知我们'int' object has no attribute 'lower'. 太糟糕了,直到运行时它才能告诉我们这一点。
据我所知, mypy 没有捕获此错误,因为它允许 参数的参数d是add_items协变的。如果我们只阅读字典,那就有意义了。如果我们只是读取,那么我们会希望参数是协变的。如果我们准备读取任何类型,那么我们应该能够读取字符串类型。当然,如果我们只是阅读,那么我们应该将其输入为typing.Mapping.
由于我们正在编写,所以我们实际上希望参数是逆变的。例如,某人传入 a 是完全有意义的Dict[Any, Any],因为它完全能够存储字符串键和整数值。
如果我们要进行读写,就别无选择,只能让参数保持不变。
有没有办法指定我们需要什么样的方差?更好的是, mypy 是否足够复杂,以至于期望它通过静态分析确定方差应该是合理的,并且这应该作为错误归档?或者 Python 中类型检查的当前状态根本无法捕获这种编程错误?
python ×3
.net ×2
c# ×2
mypy ×2
bouncycastle ×1
c++ ×1
covariance ×1
enums ×1
generator ×1
idisposable ×1
lambda ×1
rfc3161 ×1
trust ×1
typing ×1
winapi ×1