解决方案
对于这个问题,一般我们可以使用一对public和private方法配合来使用:
以下为引用的内容: public static IEnumerable<string> ToString(IEnumerable<int> source) return ToStringInternal(source); private static IEnumerable<string> ToStringInternal(IEnumerable<int> source) |
不妨再去查看一下现在的C#代码实现?
资源管理
问题
由于是延迟执行,一些原本最简单的代码模式可能就破坏了。例如:
以下为引用的内容: static Func<string> ReadAllText(string file) |
使用using来管理文件的打开关闭是最容易不过的事情了,不过现在如果您通过ReadAllText(@"C:\abc.txt")方法获得的Func<string>对象,在执行时就会抛出ObjectDisposedException。这是因为原本我们意图中的顺序:
打开文件
读取内容
关闭文件
因为有“延迟”特性,这个顺序已经变为:
打开文件
关闭文件
读取内容
这怎么能不出错?
解决方案
有朋友说,这个容易:
以下为引用的内容: static Func<string> ReadAllText(string file) return () => text; |
的确没有抛出异常了,但是这也丧失了“延迟”的特点了。我们必须让它能够在调用委托对象的时候,才去打开文件:
以下为引用的内容: static Func<string> ReadAllText(string file) |
值得一提的是,using完全可以配合yield语句使用。也就是说,您可以编写这样的代码:
以下为引用的内容: static IEnumerable<string> AllLines(string file) |
由此也可见C#编译器是多么的强大,它帮我们解决了非常重要的问题。
闭包共享
问题
其实这个问题也已经被谈过很多次了,在这里提一下主要是为了保持内容的完整性。您认为,以下代码结果如何?
以下为引用的内容: List<Action> actions = new List<Action>(); foreach (var a in actions) a(); |
它打印出来的结果是10个10,具体原因在《警惕匿名方法造成的变量共享》一文中已经有过描述,概括而来便是:各个action共享一个闭包,导致其中的“i”并不是独立的。
解决方案
解决这个问题的方法,只需让不同闭包访问的值相互独立即可。如:
以下为引用的内容: List<Action> actions = new List<Action>(); foreach (var a in actions) a(); |
关于“延迟”特性,您还有什么看法呢?
.
分页: [1] [2]
TAG: NET 特性 陷阱 延迟