gpt4 book ai didi

c# - using关键字的动态

转载 作者:太空狗 更新时间:2023-10-29 22:20:55 26 4
gpt4 key购买 nike

考虑以下代码:

// module level declaration
Socket _client;

void ProcessSocket() {
_client = GetSocketFromSomewhere();
using (_client) {
DoStuff(); // receive and send data

Close();
}
}

void Close() {
_client.Close();
_client = null;
}

鉴于代码调用了 Close() 方法,该方法关闭了 _client 套接字并将其设置为 null,同时仍在内部`using' block ,幕后到底发生了什么?套接字真的关闭了吗?有副作用吗?

附言这是在 .NET MicroFramework 上使用 C# 3.0,但我认为 c# 这种语言的功能应该相同。我问的原因是偶尔,很少,我会用完套接字(这是 .NET MF 设备上非常宝贵的资源)。

最佳答案

仍会调用 Dispose。您所做的只是将变量 _client 指向内存中的其他内容(在本例中为 null)。 _client 最初引用的对象仍将在 using 语句结束时被释放。

运行这个例子。

class Program
{
static Foo foo = null;

static void Main(string[] args)
{
foo = new Foo();

using (foo)
{
SomeAction();
}

Console.Read();
}

static void SomeAction()
{
foo = null;
}
}

class Foo : IDisposable
{
#region IDisposable Members

public void Dispose()
{
Console.WriteLine("disposing...");
}

#endregion
}

将变量设置为 null 并不会破坏对象或阻止它被 using 处置。您所做的只是更改变量的引用,而不是更改最初引用的对象。

后期编辑:

关于 MSDN 使用引用的评论中的讨论 http://msdn.microsoft.com/en-us/library/yh598w02.aspx和 OP 中的代码以及在我的示例中,我创建了一个更简单的代码版本。

Foo foo = new Foo();
using (foo)
{
foo = null;
}

(而且,是的,该对象仍会被处置。)

您可以从上面的链接推断代码正在被重写为:

Foo foo = new Foo();
{
try
{
foo = null;
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}

不会处理对象,并且与代码片段的行为不匹配。所以我通过 ildasm 查看了它,我能收集到的最好的信息是原始引用被复制到内存中的一个新地址。语句 foo = null; 适用于原始变量,但对 .Dispose() 的调用发生在复制的地址上。所以这里是我如何相信代码实际上正在被重写的原因。

Foo foo = new Foo();
{
Foo copyOfFoo = foo;
try
{
foo = null;
}
finally
{
if (copyOfFoo != null)
((IDisposable)copyOfFoo).Dispose();
}
}

作为引用,这是通过 ildasm 实现的 IL 的样子。

.method private hidebysig static void  Main() cil managed
{
.entrypoint
// Code size 29 (0x1d)
.maxstack 1
.locals init ([0] class Foo foo,
[1] class Foo CS$3$0000)
IL_0000: newobj instance void Foo::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: stloc.1
.try
{
IL_0008: ldnull
IL_0009: stloc.0
IL_000a: leave.s IL_0016
} // end .try
finally
{
IL_000c: ldloc.1
IL_000d: brfalse.s IL_0015
IL_000f: ldloc.1
IL_0010: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0015: endfinally
} // end handler
IL_0016: call int32 [mscorlib]System.Console::Read()
IL_001b: pop
IL_001c: ret
} // end of method Program::Main

我不以盯着 ildasm 为生,所以我的分析可以归类为买者自负。然而,行为就是这样。

关于c# - using关键字的动态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2513035/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com