有人可以向我解释为什么下面显示的代码在C#中有效并执行调用Console.WriteLine?
using (null)
{
Console.WriteLine ("something is here")
}
Run Code Online (Sandbox Code Playgroud)
它编译成(最后显示块).如您所见,编译器决定不执行该Dispose()方法并跳转到该endfinally指令.
IL_0013: ldnull
IL_0014: ceq
IL_0016: stloc.1
IL_0017: ldloc.1
IL_0018: brtrue.s IL_0021 // branches here and decide not to execute Dispose()
IL_001a: ldnull
IL_001b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0020: nop
IL_0021: endfinally
Run Code Online (Sandbox Code Playgroud)
但是,如果我运行以下代码,它将失败a NullReferenceException(预期):
((IDisposable)null).Dispose();
IL_0023: ldnull
IL_0024: callvirt instance void [mscorlib]System.IDisposable::Dispose()
Run Code Online (Sandbox Code Playgroud)
为什么第一个版本编译?为什么编译器决定不执行Dispose()?是否有任何其他情况下,当编译器可以决定不叫Dispose()的using块?
我正在查看Stack Overflow团队在Google Code上设计的mvc-mini-profiler,并且在入门页面上有一件事让我感到特别奇怪:
var profiler = MiniProfiler.Current; // it's ok if this is null
using (profiler.Step("Set page title"))
{
ViewBag.Title = "Home Page";
}
Run Code Online (Sandbox Code Playgroud)
如果探查器为空,它怎么能"ok"?在我看来,调用Step会抛出一个NullReferenceException.在我编程C#的所有这些年里,我从来都不知道在任何上下文中调用null引用上的方法都是"ok".这是使用子句的特殊情况吗?
我能理解这是好的(不知道它是,但显然它是?):
using (null)
{
...
}
Run Code Online (Sandbox Code Playgroud)
但是在null引用上调用方法似乎应该抛出异常,无论它是否在using子句中.有人可以解释如何在幕后翻译这样的结构,所以我可以理解为什么这样做是可以的?
请考虑以下代码:
// module level declaration
Socket _client;
void ProcessSocket() {
_client = GetSocketFromSomewhere();
using (_client) {
DoStuff(); // receive and send data
Close();
}
}
void Close() {
_client.Close();
_client = null;
}
Run Code Online (Sandbox Code Playgroud)
鉴于代码调用Close()方法,关闭_client套接字并将其设置为null,同时仍然在"using"块内,幕后究竟发生了什么?套接字真的关闭了吗?有副作用吗?
PS这是在.NET MicroFramework上使用C#3.0,但我认为c#(语言)应该具有相同的功能.我问的原因是偶尔,很少,我用完套接字(这是.NET MF设备上非常宝贵的资源).
如果依赖容器或数据访问工厂可以返回可能实现的类型,IDisposable那么客户是否有责任检查并处理它?在下面的代码中,一个数据类实现IDisposable而另一个不实现.数据访问工厂可以返回任何一个.
private static void TestPolymorphismWithDisposable()
{
// Here we don't know if we're getting a type that implements IDisposable, so
// if we just do this, then we won't be disposing of our instance.
DataAccessFactory.Resolve().Invoke();
// Do we just have to do something like this?
IFoo foo = DataAccessFactory.Resolve();
foo.Invoke();
var fooAsDisposable = foo as IDisposable;
if (fooAsDisposable != null) { fooAsDisposable.Dispose(); }
}
Run Code Online (Sandbox Code Playgroud)
我问的原因是,这似乎给客户端代码带来了负担,必须处理这个问题,在构建API时,如何让客户知道他们可能需要调用dispose?是否有更好的方法来处理客户端无需检查的情况IDisposable?
为了完整的工作示例,以下是其他类:
public interface IFoo
{ …Run Code Online (Sandbox Code Playgroud) 在应用程序中进行调试时,我发现了以下代码.这显然是错误的,但由于一些奇怪的原因它起作用,我似乎无法理解为什么.在我看来,代理将在创建后立即处理,但调用此代理上的方法可以正常连接到WCF服务.
谁能解释为什么这段代码不会爆炸?
private static IMyService _proxy = null;
private static IMyService Proxy
{
get
{
if (_proxy == null)
{
using (_proxy as IDisposable)
{
ChannelFactory<IMyService> factory =
new ChannelFactory<IMyService>("MyService");
_proxy = factory.CreateChannel();
}
}
return _proxy;
}
}
Run Code Online (Sandbox Code Playgroud) 因此,当我关闭表单时,我正在处理许多对象.即使它可能会自动处理它.但我仍然倾向于遵循处理中的"规则",希望它会坚持并帮助防止错误.
所以这就是我目前处理的方式,哪个有效.
if (connect == true)
{
Waloop.Dispose();
connect = false;
UninitializeCall();
DropCall();
}
if (KeySend.Checked || KeyReceive.Checked)
{
m_mouseListener.Dispose();
k_listener.Dispose();
}
if (NAudio.Wave.AsioOut.isSupported())
{
Aut.Dispose();
}
if (Wasout != null)
{
Wasout.Dispose();
}
if (SendStream != null)
{
SendStream.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
所以基本上,首先是如果一个博尔是真的,意味着如果它不是那些可以被忽略,因为它们没有被我想到.
其他的只是让我处理的方法,如果在那里.但这不是一个非常好的方式,我希望它有一个大功能,意思.
处置,如果没有处置.或者其他的东西.我知道他们中的许多都有"被处置"的布尔,所以如果我可以检查每个对象,并且如果它是假的则应该可以处理.