我对c#有点新手,更习惯脚本语言.我喜欢'使用'的想法,你实例化一个对象,然后只要你需要它就在它的范围内运行,然后当它完成它的目的时你让它自己处理掉.
但是,这对我来说并不自然.当人们向我展示使用它的例子时,我认为它是一个很好的工具,但在我自己的编程中解决它的问题从来没有发生过.
如何识别好的地方using以及如何将它与try-catch块结合使用.它们是否进入块内,或者您是否通常想在try块中包含using语句?
我想知道你对我所涉及的编码风格问题的看法.我意识到可能没有明确的答案,但我想看看在一个方向或另一个方向是否有强烈的偏好.
我正在通过一个解决方案using在很多地方添加语句.我常常会遇到这样的事情:
{
log = new log();
log.SomeProperty = something; // several of these
log.Connection = new OracleConnection("...");
log.InsertData(); // this is where log.Connection will be used
... // do other stuff with log, but connection won't be used again
}
Run Code Online (Sandbox Code Playgroud)
其中log.Connection是OracleConnection,它实现了IDisposable.
在我的neatnik想要改变它:
{
using (OracleConnection connection = new OracleConnection("..."))
{
log = new log();
log.SomeProperty = something;
log.Connection = conn;
log.InsertData();
...
}
}
Run Code Online (Sandbox Code Playgroud)
但是,简洁的爱好者和稍微快速完成工作的人希望这样做:
{
log = new log();
log.SomeProperty = something;
using (log.Connection = new …Run Code Online (Sandbox Code Playgroud) 正如本文所述,关于在IDisposable对象上使用的用法,它说了一个有趣的词:
...使用块,在块结束后的某个时间自动调用Dispose方法.(它可能不是立即的;它取决于CLR.)
有趣的是" 它可能不是立即的;它取决于CLR ".任何人都可以提供更多细节吗?因为我们有一些奇怪的情况下,似乎在代码中使用(新MyDisposable()){...},块结束}后它不立即呼吁MyDisposable例如Dispose方法,但一段时间后.
更新:结论对我来说,在我看来,我在其他地方有问题.我认为可以在使用块结束后的某个时间调用Dispose方法.但是当它不是那样的时候,我必须在我的代码中的其他地方找到问题.谢谢你的回复!
如果使用using子句来处置连接,那么实现IDisposable的子句中的其他项是否也会自动处理?如果没有,您如何处理确保所有IDisposable项目自动处理?
public static DataTable ReturnDataTable(
string ConnectionString, string CommandTextString, CommandType CommandType,
int CommandTimeout, List<System.Data.SqlClient.SqlParameter> ParameterList = null)
{
using (System.Data.SqlClient.SqlConnection Connection =
new System.Data.SqlClient.SqlConnection())
{
Connection.ConnectionString = ConnectionString;
System.Data.SqlClient.SqlCommand Command =
new System.Data.SqlClient.SqlCommand();
Command.Connection = Connection;
Command.CommandText = CommandTextString;
Command.CommandType = CommandType;
Command.CommandTimeout = CommandTimeout;
if (ParameterList != null)
{
if (ParameterList.Count > 0)
{
foreach (SqlParameter parameter in ParameterList)
{
Command.Parameters.AddWithValue(
parameter.ParameterName, parameter.Value);
}
}
}
System.Data.DataTable DataTable = new System.Data.DataTable();
System.Data.SqlClient.SqlDataAdapter DataAdapter =
new System.Data.SqlClient.SqlDataAdapter();
DataAdapter.SelectCommand = Command; …Run Code Online (Sandbox Code Playgroud) 我有一个应用程序,我必须从DB获取大量数据.由于它未能获得所有这些行(它接近2,000,000行...),我在中断时将其剪切,并且每次执行sql查询时每次只获得200,000行.
我使用DataTable输入所有数据(意思是 - 所有2,000,000行应该在那里).
前几次运行很好.然后它以OutOfMemoryException失败.
我的代码如下:
private static void RunQueryAndAddToDT(string sql, string lastRowID, SqlConnection conn, DataTable dt, int prevRowCount)
{
if (string.IsNullOrEmpty(sql))
{
sql = generateSqlQuery(lastRowID);
}
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
using (IDbCommand cmd2 = conn.CreateCommand())
{
cmd2.CommandType = CommandType.Text;
cmd2.CommandText = sql;
cmd2.CommandTimeout = 0;
using (IDataReader reader = cmd2.ExecuteReader())
{
while (reader.Read())
{
DataRow row = dt.NewRow();
row["RowID"] = reader["RowID"].ToString();
row["MyCol"] = reader["MyCol"].ToString();
... //In one of these rows it returns the exception.
dt.Rows.Add(row);
} …Run Code Online (Sandbox Code Playgroud) 假设我已经定义了一个类MyDisposable : IDisposable.我知道我可以IDisposable在using声明中提供一个硬编码的对象列表:
using (MyDisposable firstDisposable = new MyDisposable(),
secondDisposable = new MyDisposable())
{
// do something
}
Run Code Online (Sandbox Code Playgroud)
现在让我们说我有一些方法可以对我的一次性对象集合执行操作,我想在一个using语句中执行此操作.它可能看起来像这样(但是这当然不起作用,因为using块需要一个或多个IDisposable对象,而且我传递一个集合对象):
using (var myDisposables = GetMyDisposables())
{
foreach (var myDisposable in myDisposables)
{
DoSomething(myDisposable);
DoSomethingElse(myDisposable);
}
}
Run Code Online (Sandbox Code Playgroud)
为清楚起见,其他方法如下:
static List<MyDisposable> GetMyDisposables()
{
throw new NotImplementedException(); // return a list of MyDisposable objects
}
static void DoSomething(MyDisposable withMyDisposable)
{
// something
}
static void DoSomethingElse(MyDisposable withMyDisposable)
{
// something else
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以用using …
我很想知道这个SingleOrFallback方法是如何在MoreLinq中实现的,并发现了一些我以前没见过的东西:
public static T SingleOrFallback<T>(this IEnumerable<T> source, Func<T> fallback)
{
source.ThrowIfNull("source");
fallback.ThrowIfNull("fallback");
using (IEnumerator<T> iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
return fallback();
}
T first = iterator.Current;
if (iterator.MoveNext())
{
throw new InvalidOperationException();
}
return first;
}
}
Run Code Online (Sandbox Code Playgroud)
为什么IEnumerator<T>在using声明中?在使用foreachon 时也应该考虑这个问题IEnumerable<T>吗?
附带问题:这种方法究竟做了什么?每当源序列不包含一个项时,它是否返回后备项?
我对C++很新,但我的理解是#include语句基本上只是将#included文件的内容转储到该语句的位置.这意味着如果我的头文件中有一些'#include'和'using'语句,我的实现文件只能#include头文件,编译器不介意我不重复其他语句.
那人呢呢?
我主要担心的是,如果我不重复'#include','using',以及'typedef'(现在我想到它)语句,它会从使用它的文件中取出该信息,可能导致混乱.
我现在只是处理小型项目,它不会真正导致任何问题,但我可以想象,在有更多人工作的大型项目中,它可能成为一个重要问题.
一个例子如下:
更新:我的'Unit'函数原型在它们的返回类型和参数中有字符串,ostream和StringSet - 我没有在我的头文件中包含任何只在实现文件中使用的内容.
//Unit.h
#include <string>
#include <ostream>
#include "StringSet.h"
using std::string;
using std::ostream;
class Unit {
public:
//public members with string, ostream and StringSet
//in their return values/parameter lists
private:
//private members
//unrelated side-question: should private members
//even be included in the header file?
} ;
//Unit.cpp
#include "Unit.h"
//The following are all redundant from a compiler perspective:
#include <string>
#include <ostream>
#include "StringSet.h"
using std::string;
using std::ostream;
//implementation goes here
Run Code Online (Sandbox Code Playgroud) 我问了一个关于从函数中返回一个Disposable(IDisposable)对象的问题,但是如果我在那里提出这个问题,我认为我会讨论这个问题.
我创建了一些示例代码:
class UsingTest
{
public class Disposable : IDisposable
{
public void Dispose()
{
var i = 0;
i++;
}
}
public static Disposable GetDisposable(bool error)
{
var obj = new Disposable();
if (error)
throw new Exception("Error!");
return obj;
}
}
Run Code Online (Sandbox Code Playgroud)
我故意用这种方式编码,因为我打电话给:
using (var tmp = UsingTest.GetDisposable(true)) { }
Run Code Online (Sandbox Code Playgroud)
使用调试器,我注意到该Dispose方法永远不会执行,即使我们已经实例化了一个Disposable对象.如果我正确地理解了这个目的Dispose,如果这个类实际上已经打开了句柄之类的东西,那么我们一旦完成它们就不会关闭它们.
我问这个问题是因为这种行为符合我的期望,但在相关问题的答案中,人们似乎表明using会照顾一切.
如果using仍然以某种方式处理所有这些,有人可以解释我错过了什么?但是,如果这段代码确实会导致资源泄漏,你会如何建议我编写代码GetDisposable(条件是我必须实例化IDisposable对象并运行可能在return语句之前抛出异常的代码)?
关于在单个'using'语句中使用嵌套一次性用法的快速问题:我应该写出每个一次性使用语句,还是可以将它们嵌入一个?例:
using( FileStream inFile = new FileStream( "myFile.txt", FileMode.Open ) )
using( GZipStream gzip = new GZipStream( inFile, CompressionMode.Decompress ) )
using( FileStream outFile = new FileStream( "myNewFile.txt", FileMode.CreateNew ) )
{
gzip.CopyTo( outstream );
}
Run Code Online (Sandbox Code Playgroud)
与
using( GZipStream gzip = new GZipStream( new FileStream( "myFile.txt", FileMode.Open ), CompressionMode.Decompress ) )
using( FileStream outFile = new FileStream( "myNewFile.txt", FileMode.CreateNew ) )
{
gzip.CopyTo( outstream );
}
Run Code Online (Sandbox Code Playgroud)
好奇的是,当块执行完毕时,来自"myFile.txt"的未命名的FileStream会被清除,因为它位于带有GZipStream的using语句中,或者它是否保持打开状态并且需要在此之后的某个时间进行清理.
编辑:为了清楚,我不是在询问有关使用语句嵌套的问题.我问的是,在另一个IDisposable的'using'语句中创建的IDisposable是否会在块的末尾被处理掉.任何解释为什么或为什么不会被赞赏.
using-statement ×10
c# ×9
idisposable ×6
.net ×1
c++ ×1
coding-style ×1
datareader ×1
dispose ×1
exception ×1
header-files ×1
ienumerable ×1
ienumerator ×1
include ×1
sql ×1