C# 在一个班级中启动一个班级的正确方式是什么?
在一个班级中启动一个班级的正确方式是什么?我应该将StreamWriter放入一个方法中吗?还是这样好C# 在一个班级中启动一个班级的正确方式是什么?,c#,class,C#,Class,在一个班级中启动一个班级的正确方式是什么?我应该将StreamWriter放入一个方法中吗?还是这样好 class Class1 { public static string config = "file.config"; StreamWriter writer = new StreamWriter(config); public void print (string log) { writer.WriteLine(log); } public
class Class1
{
public static string config = "file.config";
StreamWriter writer = new StreamWriter(config);
public void print (string log)
{
writer.WriteLine(log);
}
public void log_close()
{
writer.Close();
}
}
您的关闭逻辑不是线程安全的,并且不遵循建议 您应该使用一次性模式,因为FileStream实现IDisposable
class Class1 : IDisposable
{
public string config = "file.config";
StreamWriter writer = new StreamWriter(config);
public void print (string log)
{
writer.WriteLine(log);
}
public void log_close()
{
Dispose();
}
public void Dispose()
{
if (writer != null)
writer.Close();
writer = null;
}
}
现在,您的Class1实例可以与using
语句一起使用:
using (var c = new Class1())
{
c.print("That's all");
}
无需调用Dispose()或close() 你所做的没有什么不对。除非以后需要将
编写器重新初始化为新对象,否则没有理由将其放入方法中
但是,按照编写方式,它允许更改config
字符串。此时,您似乎希望将writer
的实例化移动到一个方法中,以便在第一次使用时以及config
字符串更改时可以实例化一个新的方法。但是,如果类构造后不需要更改config
,则应在构造函数中请求文件名,并在其中实例化对象:
class Logger : IDisposable
{
StreamWriter writer;
public void Logger(string configFileName)
{
writer = new StreamWriter(configFileName);
}
public void Print(string text)
{
writer.WriteLine(text);
}
public void Dispose()
{
writer.Dispose();
}
}
正如其他人所指出的,让类实现IDisposable和使用更好的命名约定也是可取的。您已经在本地类私有范围内声明了StringWriter。这通常是在多个方法之间共享变量时完成的。但是,您应该管理公共变量,特别是那些实现IDisposable的变量,例如StringBuilder
当您使用两种方法访问StringBuilder时,可以在该范围内声明它。但是,当对象被垃圾收集器破坏时,应该手动关闭并处置该对象
您可以使用C#类析构函数,这一点非常详细。请考虑以下代码:
class LogWriter : IDisposable
{
public const string configFileName = "file.config";
StreamWriter writer = new StreamWriter(configFileName);
public void Print(string log)
{
writer.WriteLine(log);
}
public void CloseLog()
{
writer.Close();
}
public void Dispose()
{
CloseLog();
}
}
当您有一些应该发布的资源(如文件)时,最好的方法是实现IDisposable
接口。您的类的用户将知道,该类应该在使用后进行处置
还有命名——在C#中,我们将方法命名为PascalCase。并为类和变量提供更有意义的名称:LogWriter而不是Class1,configFileName而不是config。在编译时初始化的字段的初始化被移到构造函数的顶部
class Class1
{
String foo = "bar";
String bar;
public Class1()
{
bar = "baz";
}
}
变成
.class private auto ansi beforefieldinit FieldInitialization.Class1
extends [mscorlib]System.Object
{
.field private string bar
.field private string foo
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
IL_0000: ldarg.0
IL_0001: ldstr "bar"
IL_0006: stfld string FieldInitialization.Class1::foo
IL_000b: ldarg.0
IL_000c: call instance void [mscorlib]System.Object::.ctor()
IL_0011: nop
IL_0012: nop
IL_0013: ldarg.0
IL_0014: ldstr "baz"
IL_0019: stfld string FieldInitialization.Class1::bar
IL_001e: nop
IL_001f: ret
}
}
因此,选择在哪里初始化它们实际上是一个风格问题。但是,如果要初始化的对象依赖于其他非静态字段、方法或属性,则必须在构造函数中初始化它们。否则将出现编译错误:
字段初始值设定项不能引用非静态字段、方法或属性
对于可IDispiable资源,例如StreamWriter(或位图),您应该记住其他人指出的问题。请使用{}
标记格式化代码。现在,您应该已经学会了。您的示例无法编译,writer
的初始化器无法引用config
。最后一行writer=null
的目的是什么?@John-对Dispose()safe进行多次调用。通常会有一个bool isDisposed
字段,我的字段是一个快捷方式。应该是class Class1:IDisposable
,而不是class Class1:IDisposable()
IL转储如何回答这个问题?@HenkHolterman OP问“我应该把StreamWriter放在一个方法中吗?或者这很好?”,我还指出,这是一个风格问题,对程序没有任何影响。@HenkHolterman这可能是这里的具体情况,但问题更广泛:“在一个类中启动一个类的正确方式是什么?”。有不同的方法可以做到这一点。在析构函数中处理对象并不好。想法是尽快释放资源,而不是让它们保持打开状态,直到GC开始破坏您的对象。