C# 中的嵌套 using 语句
我正在做一个项目。我必须比较两个文件的内容,看看它们是否精确匹配。
在进行大量错误检查和验证之前,我的初稿是:
DirectoryInfo di = new DirectoryInfo(Environment.CurrentDirectory + "\\TestArea\\");
FileInfo[] files = di.GetFiles(filename + ".*");
FileInfo outputFile = files.Where(f => f.Extension == ".out").Single<FileInfo>();
FileInfo expectedFile = files.Where(f => f.Extension == ".exp").Single <FileInfo>();
using (StreamReader outFile = new StreamReader(outputFile.OpenRead()))
{
using (StreamReader expFile = new StreamReader(expectedFile.OpenRead()))
{
while (!(outFile.EndOfStream || expFile.EndOfStream))
{
if (outFile.ReadLine() != expFile.ReadLine())
{
return false;
}
}
return (outFile.EndOfStream && expFile.EndOfStream);
}
}
嵌套 using
语句似乎有点奇怪。
有更好的方法吗?
I am working on a project. I have to compare the contents of two files and see if they match each other precisely.
Before a lot of error-checking and validation, my first draft is:
DirectoryInfo di = new DirectoryInfo(Environment.CurrentDirectory + "\\TestArea\\");
FileInfo[] files = di.GetFiles(filename + ".*");
FileInfo outputFile = files.Where(f => f.Extension == ".out").Single<FileInfo>();
FileInfo expectedFile = files.Where(f => f.Extension == ".exp").Single <FileInfo>();
using (StreamReader outFile = new StreamReader(outputFile.OpenRead()))
{
using (StreamReader expFile = new StreamReader(expectedFile.OpenRead()))
{
while (!(outFile.EndOfStream || expFile.EndOfStream))
{
if (outFile.ReadLine() != expFile.ReadLine())
{
return false;
}
}
return (outFile.EndOfStream && expFile.EndOfStream);
}
}
It seems a little odd to have nested using
statements.
Is there a better way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
首选方法是仅在最后一个
using
语句后面放置一个左大括号{
,如下所示:The preferred way to do this is to only put an opening brace
{
after the lastusing
statement, like this:如果对象具有相同类型,您可以执行以下操作
If the objects are of the same type you can do the following
当
IDisposable
具有相同类型时,您可以执行以下操作:using
有关于此语言功能的文档。无论
IDisposable
是否属于同一类型,您都可以执行以下操作:When the
IDisposable
s are of the same type, you can do the following:The MSDN page on
using
has documentation on this language feature.You can do the following whether or not the
IDisposable
s are of the same type:从 C# 8.0 开始,您可以使用 using 声明。
这将在变量范围的末尾(即方法的末尾)处理使用的变量。
Since C# 8.0 you can use a using declaration.
This will dispose of the using variables in the end of the scope of the variables, i.e. in the end of the method.
如果您不介意在 using 块之前声明 using 块的变量,则可以在同一个 using 语句中声明它们。
这样,x 和 y 只是 IDisposable 类型的占位符变量,供 using 块使用,并且您可以在代码中使用 t 和 u。只是想我会提一下。
if you don't mind declaring the variables for your using block before the using block, you could declare them all in the same using statement.
That way, x and y are just placeholder variables of type IDisposable for the using block to use and you use t and u inside your code. Just thought i'd mention.
using 语句在 IDisposable 接口上工作,因此另一个选择可能是创建某种类型的复合类,该类实现 IDisposable 并引用您通常放入 using 语句中的所有 IDisposable 对象。这样做的缺点是,您必须首先在范围之外声明变量,以便它们在 using 块中有用,需要比其他一些建议所需的更多行代码。
在本例中,DisposableCollection 的构造函数是一个 params 数组,因此您可以输入任意数量的参数。
The using statement works off of the IDisposable interface so another option could be to create some type of composite class that implements IDisposable and has references to all of the IDisposable objects you would normally put in your using statement. The down side to this is that you have to declare your variables first and outside of the scope for them to be useful within the using block requiring more lines of code than some of the other suggestions would require.
The constructor for DisposableCollection is a params array in this case so you can feed in as many as you like.
如果您想有效地比较文件,则根本不要使用 StreamReaders,这样就不需要使用 - 您可以使用低级流读取来拉入数据缓冲区进行比较。
您还可以首先比较文件大小等内容,以快速检测不同的文件,从而避免自己读取所有数据。
If you want to compare the files efficiently, don't use StreamReaders at all, and then the usings aren't necessary - you can use low level stream reads to pull in buffers of data to compare.
You can also compare things like the file size first to quickly detect different files to save yourself having to read all the data, too.
你也可以说:
但有些人可能会觉得很难读。顺便说一句,作为对您的问题的优化,为什么不先检查文件大小是否相同,然后再逐行进行呢?
You can also say:
But some people might find that hard to read. BTW, as an optimization to your problem, why dont you check that the file sizes are the same size first, before going line by line?
您可以使用逗号将多个一次性对象分组在一个 using 语句中:
You can group multiple disposable objects in one using-statement with commas:
您可以省略除了最里面的使用之外的所有使用的括号:
我认为这比将多个相同类型的内容放在同一个使用中更干净,正如其他人所建议的那样,但我相信很多人会认为这很令人困惑
You could omit the brackets on all but the inner-most using:
I think this is cleaner than putting several of the same type in the same using, as others have suggested, but I'm sure many people will think this is confusing
另外,如果您已经知道路径,则无需扫描目录。
相反,我会推荐这样的东西:
Path.Combine
将向路径添加文件夹或文件名,并确保路径和名称之间正好有一个反斜杠。File.OpenText
将打开一个文件并一次性创建一个StreamReader
。通过在字符串前添加 @ 前缀,您可以避免转义每个反斜杠(例如,
@"a\b\c"
)Also, if you already know the paths, there's no point is scanning the directory.
Instead, I would recommend something like this:
Path.Combine
will add a folder or filename to a path and make sure that there is exactly one backslash between the path and the name.File.OpenText
will open a file and create aStreamReader
in one go.By prefixing a string with @, you can avoid having to escape every backslash (eg,
@"a\b\c"
)为了增加清晰度,在这种情况下,由于每个连续语句都是单个语句(而不是块),因此您可以省略所有括号:
And to just add to the clarity, in this case, since each successive statement is a single statement, (and not a block), you can omit all the brackets :
这没什么奇怪的。
using
是确保代码块完成后处理对象的一种简写方式。如果您的外部块中有一个一次性对象,而内部块需要使用,这是完全可以接受的。There's nothing odd about it.
using
is a shorthand way of ensuring the disposal of the object once the code block is finished. If you have a disposable object in your outer block that the inner block needs to use, this is perfectly acceptable.您是否还想知道是否有更好的方法来比较文件?
我更喜欢计算两个文件的 CRC 或 MD5 并进行比较。
例如,您可以使用以下扩展方法:
一旦完成,比较文件就非常容易:
您可以使用内置的 System.Security.Cryptography.MD5 类,
但计算出的哈希值是一个 byte[],所以您仍然需要比较这两个数组。
Are you also asking if there is a better way to compare to files?
I prefer calculating a CRC or MD5 for both files and compare those.
For example you could use the following extension method:
Once you've done that it's pretty easy to compare files:
You could use the built in System.Security.Cryptography.MD5 class,
but the calculated hash is a byte[] so you'd still have to compare those two arrays.
这是正常的使用方式并且工作完美。尽管还有一些其他方法可以实现这一点。
几乎每个答案都已经存在于这个问题的回答中。但在这里我将所有这些都列出来。
已使用
选项 1
选项 2
Its the normal way of use and works perfect. Although there are some other ways of implementing this.
Almost every answer is already present in this question's response. But here I am listing all of them together.
Already Used
Option 1
Option 2
当我编码时,这些也会时不时地出现。您可以考虑将第二个 using 语句移到另一个函数中。
These come up time to time when I code as well. You could consider move the second using statement into another function.
我想我可能已经找到了一种语法上更清晰的方法来声明这个 using 语句,并且它似乎对我有用?在 using 语句中使用 var 作为类型而不是 IDisposable 似乎可以动态推断两个对象的类型,并允许我实例化两个对象并调用它们分配的类的属性和方法,如
using(var uow = new UnitOfWorkType1(), uow2 = new UnitOfWorkType2()){}。
如果有人知道为什么这是不对的,请告诉我
I think I may have found a syntactically cleaner way of declaring this using statement, and it appears to work for me? using var as your type in the using statement instead of IDisposable seems to dynamically infer type on both objects and allows me to instantiate both of my objects and call their properties and methods of the class they are allocated with, as in
using(var uow = new UnitOfWorkType1(), uow2 = new UnitOfWorkType2()){}.
If anyone knows why this isn't right, please let me know