在课堂上开课的正确方法是什么?

时间:2012-07-13 20:23:58

标签: 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 void log_close() 
   { 
      writer.Close();
   }
}

5 个答案:

答案 0 :(得分: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()。

答案 1 :(得分: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。

答案 2 :(得分: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并使用更好的命名约定。

答案 3 :(得分:0)

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

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

您可以使用C#类析构函数,详细信息为here

答案 4 :(得分:-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这样的IDispisable资源(例如Bitmap),您应该记住其他人指出的问题。