Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#使用语句自动处理对象的替代语法?_C#_.net_Idisposable - Fatal编程技术网

C#使用语句自动处理对象的替代语法?

C#使用语句自动处理对象的替代语法?,c#,.net,idisposable,C#,.net,Idisposable,我想知道是否有人能想出一种方法来实现一种类似于C#中using语句但语法更简洁的机制 在C++/CLR中,您可以编写 MyClass NewObject; MyClass在这里是一个托管类。一旦变量超出范围,将调用Dispose。本质上,它与使用的做了同样的事情,但方式更好 因此,与其写作 using (MyClass NewObject1=new MyClass()) { xxxx; using (MyClass NewObject2=new MyClass() {

我想知道是否有人能想出一种方法来实现一种类似于C#中using语句但语法更简洁的机制

C++/CLR中,您可以编写

MyClass NewObject;
MyClass
在这里是一个托管类。一旦变量超出范围,将调用Dispose。本质上,它与使用的做了同样的事情,但方式更好

因此,与其写作

using (MyClass NewObject1=new MyClass())
{
    xxxx;
    using (MyClass NewObject2=new MyClass()
    {
    }
}
(我认为这看起来不是很干净,为每个新变量打开一个新块也很乏味)

我更喜欢这样的东西:

autodispose MyClass NewObject1=new MyClass();
xxxx;
autodispose MyClass NewObject2=new MyClass();
有人认为有可能实现这样的事情吗?AOP或代码契约的框架似乎使用注入代码的机制,但我不确定它们是如何做到的

MyClass在这里是一个托管类。一旦变量超出范围,就会调用Dispose

即使在C++/CLR中,情况也并非如此。我的理解是,C++或CLR仍然依赖于托管对象的核心.NET垃圾回收器,而不是传统的C++析构函数语义…根据这些规则,对象在将来的某个不确定的点上被处理;它可能是立即的。。。但更可能的情况是不会。可能很快就会。。。但你不能肯定


即使在C#世界中,
using
块也是为非托管资源(即:RAM以外的任何资源)保留的。您不需要将任何对象放在using块中:大多数东西都可以在没有using块的情况下安全地创建。当您需要using块时,就是当您正在创建的类型中包含网络连接、数据库连接、文件句柄、gdi资源、系统计时器等内容时。

如果您希望压缩using语句以简化键入,为什么不这样做呢

using (MyClass class1 = new MyClass())
using (MyClass class2 = new MyClass())
using (MyClass class3 = new MyClass()) {
    object xxxx;
    // do some stuff
}
你可以给自己留一些花括号和几行额外的线,因为这似乎是你想要的,但并不重要。如果你是强迫症患者

using (var class1 = new MyClass())
using (var class2 = new MyClass())
using (var class3 = new MyClass()) {
    object xxxx;
    // do some stuff
}

顺便说一句,使用对C#来说是件好事。您可以定义变量的范围,并且您确切地知道该变量的范围是什么,以及何时结束。否则,作用域可能会一直扩展到其他函数(例如,传递对函数的引用,或另一个对象持有对函数的引用)。

虽然我没有答案,但我觉得值得将其作为答案而不仅仅是注释来写。据我所知,目前得票最多的答案是不正确的。根据Gordon Hogenson在《C++/CLI基础》中的说法,它确实支持“语法糖分或处理技巧”。。。。“总而言之,在块的末尾,堆分配的对象被立即删除,而不是懒洋洋地进行垃圾收集,因此,在删除时会立即调用析构函数。”-emphasis mine,第63页堆栈与堆语义之比

C++程序员(预智能指针)习惯于他们必须删除的所有新内容。但是,当C++程序员创建一个局部变量时,它就不必放到堆上。可以使用堆栈语义,然后不必显式删除对象

void Class::SomeMethod()
{ 
   DbConnection connection;  //No memory leak if not deleted
   DbConnection leaky_connection = new DbConnection(); //on the heap will leak if not deleted
}
在C++/CLI中,堆分配看起来有些不同:

DbConnection^ connection = gcnew DbConnection();

但是由于MS知道C++程序员被用来堆叠语义,所以允许栈语义版本:

DbConnection connection;
假设存在:

~DbConnection()
{
   //Close the connection
}
堆栈语义版本将在使用连接的方法末尾立即调用析构函数

我认为在C#中实现这一点的困难与为什么在C++/CLI中允许它相反(在这里我可能会遇到麻烦)。C#程序员习惯于让垃圾收集器处理事情。他们可以分配一个本地对象,将其放入一个非本地容器中,而不用担心它在方法结束时超出范围。GC知道它在集合中,并且不会过早地将其销毁。C#总是处理对象引用,并且没有明确指定堆与堆栈存储。在C#中实现这种“处理技巧”可能会破坏许多代码和期望


事实上,即使使用语句语法也会在C#中产生意想不到的麻烦。不久前我写了我最喜欢的例子

这个问题已经问了9年了,现在有了更好的答案

引入C#8

using声明是一个变量声明,前面有using关键字。它告诉编译器要声明的变量应该在封闭范围的末尾处理

根据原来的问题,不是写:

使用(MyClass NewObject1=new MyClass())
{
//在这里插入更多代码;
使用(MyClass NewObject2=newmyclass()
{
}
}
你可以改为写:

使用var newObject1=new MyClass();
//在这里插入更多代码;
使用var newObject2=new MyClass();

对象将在超出范围时被处理。

使用
仍然比其他方法更干净(
尝试
/
最后
,blech)如果
MyClass
是一个托管类,没有实现
IDisposable
,你是。你可以使用获得范围,但你的偏好会丢失(至少无需进一步装饰)是的,但没有C++/CLI用堆栈语义处理堆管理对象的技巧那么清晰,而OP就是在用堆栈语义处理堆管理对象。我希望我有一个答案。我不能和C++/CLR说话,但我想它至少在对象超出范围时一致调用其析构函数更好,不是吗?@Joel这不是真的。在C++/CLI中,你可以处理heap具有堆栈语义的托管对象。这实际上是“语法上的甜言蜜语或处理技巧”。“总而言之,在块末尾立即删除堆分配的对象,而不是延迟垃圾收集,因此,析构函数是cal