C# 当外部仅用于构造内部时,避免使用嵌套块
通常,使用块的C# 当外部仅用于构造内部时,避免使用嵌套块,c#,using,idisposable,C#,Using,Idisposable,通常,使用块的IDisposable对象本身是由另一个IDisposable对象构造的,例如 using (FileStream stream = File.Open(path, FileMode.Open)) using (MyObject obj = new MyObject(stream)) { // do something with obj } 不幸的是,上面的代码使文件流保持打开状态,直到MyObject对象被释放 要在MyObject构造函数完成后立即处理文件流,我可以改为编
IDisposable
对象本身是由另一个IDisposable
对象构造的,例如
using (FileStream stream = File.Open(path, FileMode.Open))
using (MyObject obj = new MyObject(stream))
{
// do something with obj
}
不幸的是,上面的代码使文件流保持打开状态,直到MyObject
对象被释放
要在MyObject
构造函数完成后立即处理文件流,我可以改为编写:
MyObject CreateMyObject(string path)
{
using (FileStream stream = File.Open(path, FileMode.Open))
{
return new MyObject(stream);
}
}
using (MyObject obj = CreateMyObject(path))
{
// do something with obj
}
但我不喜欢这种冗长的解决方案。我尝试用lambda替换CreateMyObject()
,但找不到合法的语法。有没有一种方法可以不调用自定义创建者函数来实现这一点
编辑:记住一些评论,我应该指出,我试图避免
try
…最终
——这是首先使用块的的主要原因
附加说明:MyObject对象是根据流中的信息构造的,即其构造函数读取流的整体内容。MyObject中没有其他方法引用该流。流的内容可能来自任何地方—文件、资源、Internet套接字等。虽然我看不到避免creator函数的方法,但您可以使其足够通用,以便定义一次并用于任何类:
static T WithStream<T>(string path, Func<FileStream, T> getter)
{
using (FileStream stream = File.Open(path, FileMode.Open))
{
return getter(stream);
}
}
class MyObject : IDisposable
{
public MyObject (Stream stream){ /* Work with stream */}
public void Dispose(){}
}
static void Main()
{
using (MyObject obj = WithStream("path", fs => new MyObject(fs)))
{
// do something with obj
}
}
static T with stream(字符串路径,Func getter)
{
使用(FileStream-stream=File.Open(路径,FileMode.Open))
{
返回吸气剂(流);
}
}
类MyObject:IDisposable
{
公共MyObject(流){/*使用流*/}
public void Dispose(){}
}
静态void Main()
{
使用(MyObject obj=WithStream(“path”,fs=>newmyobject(fs)))
{
//用obj做点什么
}
}
虽然我看不到避免creator函数的方法,但您可以使其足够通用,只需定义一次即可用于任何类:
static T WithStream<T>(string path, Func<FileStream, T> getter)
{
using (FileStream stream = File.Open(path, FileMode.Open))
{
return getter(stream);
}
}
class MyObject : IDisposable
{
public MyObject (Stream stream){ /* Work with stream */}
public void Dispose(){}
}
static void Main()
{
using (MyObject obj = WithStream("path", fs => new MyObject(fs)))
{
// do something with obj
}
}
static T with stream(字符串路径,Func getter)
{
使用(FileStream-stream=File.Open(路径,FileMode.Open))
{
返回吸气剂(流);
}
}
类MyObject:IDisposable
{
公共MyObject(流){/*使用流*/}
public void Dispose(){}
}
静态void Main()
{
使用(MyObject obj=WithStream(“path”,fs=>newmyobject(fs)))
{
//用obj做点什么
}
}
您可以像这样调用一些魔法:
TResult CreateUsingDisposable<TDisposable, TResult>(TDisposable disposable, Func<TDisposable, TResult> getResult)
where TDisposable : IDisposable
{
using (disposable)
{
return getResult(disposable);
}
}
using (var obj = CreateUsingDisposable(new FileStream(path, FileMode.Open), stream => new MyObject(stream)))
{
}
你可以像这样使用一些魔法:
TResult CreateUsingDisposable<TDisposable, TResult>(TDisposable disposable, Func<TDisposable, TResult> getResult)
where TDisposable : IDisposable
{
using (disposable)
{
return getResult(disposable);
}
}
using (var obj = CreateUsingDisposable(new FileStream(path, FileMode.Open), stream => new MyObject(stream)))
{
}
使用
块根本不需要,只需创建流,传递到MyObject
,然后调用stream.Dispose()
。当然,您需要将其包装成一个try-catch
这样写有什么意义?为什么您只需要构造函数中的流?您知道obj=。。。;使用(obj){..}
是一件事,对吗?不需要初始化变量并将其包装在单个块中。如果您担心异常发生时,obj
可能无法处理,只需使用try。。最后
您自己,而不是使用
,。为什么要将流传递给构造函数?如果您不需要一直使用流,为什么需要将其作为构造函数参数传递?也许构造器不应该获取流,而应该获取您想要读取的内容。或者它可以在那里获取文件路径并创建和使用它。MyObject
应该是reader类还是仅仅是保存您想要阅读的信息的类?它不应该同时用于这两个方面,因为这是两个独立的关注点。您根本不需要使用块,只需创建流,传递到MyObject
,然后调用stream.Dispose()
。当然,您需要将其包装成一个try-catch
这样写有什么意义?为什么您只需要构造函数中的流?您知道obj=。。。;使用(obj){..}
是一件事,对吗?不需要初始化变量并将其包装在单个块中。如果您担心异常发生时,obj
可能无法处理,只需使用try。。最后
您自己,而不是使用
,。为什么要将流传递给构造函数?如果您不需要一直使用流,为什么需要将其作为构造函数参数传递?也许构造器不应该获取流,而应该获取您想要读取的内容。或者它可以在那里获取文件路径并创建和使用它。MyObject
应该是reader类还是仅仅是保存您想要阅读的信息的类?它不应该同时用于这两个方面,因为这是两个独立的关注点。当您使用(obj)
?@maccettura访问时,流不会被处理掉吗?这就是重点。您希望在MyObject
构造函数完成后立即关闭流。忘记“魔力”。第二段代码正是我绝望地挣扎着想要的。谢谢(我可以建议你从你的答案中编辑第一个答案吗?@IanGoldby我认为他不应该。他提出了一个非常好的观点,即最好的方式是更具可读性的方式。本页上的其他解决方案可以说只不过是一种以牺牲成本为代价的聪明练习readability@MickyD你的意思是保留“聪明”但不太清晰的解决方案,作为无意义的好解决方案的对比?我不确定我是否同意-一个清晰简单的解决方案有其自身的优点。当您使用(obj)
,@maccettura时,流不会被处理掉吗?这就是重点。您希望在MyObject
构造函数完成后立即关闭流。忘记“魔力”。第二段代码正是我绝望地挣扎着想要的。谢谢(我可以建议你从你的答案中编辑第一个答案吗?@IanGoldby我认为他不应该。他提出了一个非常好的观点,即最好的方式是更具可读性的方式。其他的