简体   繁体   English

好奇的 C# 使用语句扩展

[英]Curious C# using statement expansion

I've run ildasm to find that this:我运行 ildasm 发现:

    using(Simple simp = new Simple())
    {
        Console.WriteLine("here");
    }

generates IL code that is equivalent to this:生成与此等效的 IL 代码:

    Simple simp = new Simple();
    try
    {
        Console.WriteLine("here");
    }
    finally
    {
        if(simp != null)
        {
            simp.Dispose();
        }
    }

and the question is why the hell does it check null in the finally?问题是为什么它会在finally中检查null? The finally block will only be executed if the try block is executed, and the try block will only be executed if the Simple constructor succeeds (Ie does not throw an exception), in which case simp will be non-null. finally 块只有在 try 块被执行的情况下才会被执行,而 try 块只有在 Simple 构造函数成功(即不抛出异常)的情况下才会被执行,在这种情况下 simp 将是非空的。 (If there is some fear that some intervening steps might come between the Simple constructor and the beginning of the try block, then that would really be a problem because then an exception might be thrown that would prevent the finally block from executing at all.) So, why the hell? (如果担心在 Simple 构造函数和 try 块的开头之间可能会出现一些中间步骤,那么这确实是一个问题,因为可能会抛出一个异常,从而阻止 finally 块的执行。)那么,到底是为什么?

Putting aside (please) the argument of whether the using statement is better than try-finally, I write my try-finally blocks as:撇开(请)使用语句是否比 try-finally 更好的论点,我将 try-finally 块写为:

    Simple simp = new Simple();
    try
    {
        Console.WriteLine("here");
    }
    finally
    {
        simp.Dispose();
        simp = null;        // sanity-check in case I touch simp again
                            // because I don't rely on all classes
                            // necessarily throwing
                            // ObjectDisposedException
    }

No, the finally block will ALWAYS be executed.不,finally 块将始终被执行。 You may not be getting the object from a new but from some other function that returns your object - and it might return NULL.您可能不是从 new 中获取对象,而是从其他返回对象的函数中获取对象 - 它可能返回 NULL。 using() is your friend! using() 是你的朋友!

dss539 was kind enough to suggest I include his note: dss539 好心地建议我把他的笔记包括在内:

using(Simple simp = null) 

is yet another reason that the expansion must check for null first.是扩展必须首先检查 null 的另一个原因。

using(Simple simp = null)是扩展必须首先检查 null 的另一个原因。

MSDN on the using statement.MSDN上的 using 语句。

What I think is strange is that it doesn't expand to:我认为奇怪的是它没有扩展到:

Simple simp = new Simple();
Simple __compilergeneratedtmpname = simp;
try
{
    Console.WriteLine("here");
}
finally
{
    if(__compilergeneratedtmpname != null)
    {
        __compilergeneratedtmpname.Dispose();
    }
}

It appears that your comment:看来你的评论:

"If there is some fear that some intervening steps might come between the Simple constructor and the beginning of the try block, then that would really be a problem because then an exception might be thrown that would prevent the finally block from executing at all." “如果有人担心 Simple 构造函数和 try 块的开头之间可能会出现一些干预步骤,那么这真的是一个问题,因为可能会抛出一个异常,从而阻止 finally 块的执行。”

is possibly dead on.可能已经死了。 See:看:

Atomicity & Asynchronous Exception Failures 原子性和异步异常失败

I also want to note the issue(s) with WCF and using:我还想注意 WCF 和使用的问题:

Avoiding Problems with the Using Statement and WCF Service Proxies which references: 避免使用语句和 WCF 服务代理出现问题,其中引用:

Avoiding Problems with the Using Statement避免使用语句出现问题

The code must be translated this way to avoid possible NullReferenceException when disposing the object.必须以这种方式翻译代码,以避免在处理对象时可能出现NullReferenceException As per C# language reference , the using statement accepts not only a local variable declaration as its first nonterminal resource_acquisition symbol, but any expression .根据C# 语言参考using 语句不仅接受局部变量声明作为其第一个非终结符resource_acquisition符号,还接受任何表达式 Consider the following code:考虑以下代码:

DisposableType @object = null;
using(@object) {
    // whatever
}

Clearly, unless null-conditional @object?.Dispose() in the finnaly block, an exception would ensue.显然,除非在finnaly块中使用空条件@object?.Dispose() ,否则会发生异常。 The null check is superfluous only when the expression is of a non-nullable value type (non-nullable struct).只有当表达式是不可为空的值类型(不可为空的结构)时,空检查才是多余的。 And indeed, according to the aforementioned language reference it is absent in such case.事实上,根据上述语言参考,在这种情况下是不存在的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM