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

クロージングロジックはスレッドセーフではなく、推奨事項に従っていません。

FileStreamはIDisposableを実装しているため、Disposableパターンを使用する必要があります。

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

usingこれで、Class1インスタンスを次のステートメントで使用できます。

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という名前を付けます。そして、クラスと変数にもっと意味のある名前を付けます。Class1の代わりにLogWriter、configの代わりにconfigFileNameを付けます。

于 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をローカルクラスのプライベートスコープで宣言しました。これは通常、変数が複数のメソッド間で共有されている場合に行われます。ただし、パブリック変数、特にStringBuilderなどのIDisposableを実装する変数を管理する必要があります。

2つのメソッドで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(またはビットマップなど)のようなIDispisableリソースの場合、他の人が指摘した問題に留意する必要があります。

于 2012-07-13T20:36:01.590 に答える