C# 在一个班级中启动一个班级的正确方式是什么?

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

在一个班级中启动一个班级的正确方式是什么?我应该将StreamWriter放入一个方法中吗?还是这样好

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开始破坏您的对象。