0

在课堂上开课的正确方法是什么?我应该把 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();
   }
}
4

5 回答 5

2

您的关闭逻辑不是线程安全的,并且不遵循建议。

您应该使用 Disposable 模式,因为 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()。

于 2012-07-13T20:27:24.880 回答
1

考虑以下代码:

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。

于 2012-07-13T20:31:48.320 回答
0

你在做什么没有错。除非您稍后需要重新初始化writer新对象,否则没有理由将其放入方法中。

但是,这种编写方式允许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并使用更好的命名约定也是可取的。

于 2012-07-13T20:28:05.753 回答
0

您已经在本地类私有范围内声明了您的 StringWriter。这通常在多个方法之间共享变量时完成。但是,您应该管理您的公共变量,尤其是那些实现 IDisposable 的变量,例如 StringBuilder。

当您以两种方法访问 StringBuilder 时,可以在该范围内声明它。但是,当对象被垃圾收集器销毁时,您应该手动关闭并处置该对象。

您可以使用 C# 类析构函数,这里有详细介绍

于 2012-07-13T20:29:55.790 回答
-1

像这样初始化的字段的初始化在编译时移动到构造函数的顶部。

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
    }
}

因此,您选择在哪里初始化它们实际上是一个风格问题。但是,当您要初始化的对象依赖于其他非静态字段、方法或属性时,您必须在构造函数中初始化它们。否则你会得到编译错误:

字段初始值设定项不能引用非静态字段、方法或属性

对于像 StreamWriter(或 Bitmap)这样的 IDispisable 资源,您应该牢记其他人指出的问题。

于 2012-07-13T20:36:01.590 回答