2011-01-11 9 views
1

私はすでに存在し、すべてのメソッドが静的であるC#の密封クラスを持っています。 xmlファイルでいくつかのファイル操作を行います。今日までのファイル名はソースにハードコードされていました。 これで、設定ファイルを設定ファイルに保存する必要があります。静的密封クラスの実装上の問題

問題は次のとおりです: クラスは抽出されるので、ハードコードされた文字列を置き換えるいくつかのローカル静的ファイル名変数にfilenameを割り当てるために静的な 'Initialize'メソッドを公開する必要があります。 私は常に、Initializeは最初に呼び出され、その後は必ず呼び出さなければなりません。 それでは、より良い方法はコンストラクタを持つことです。私は書き込むことはできません。

これを行うより良い方法が、型の安全性を確保したいです。

+4

郵便番号、または何もできません。 – abelenky

+0

静的コンストラクタは静的プロパティ/フィールドに値を割り当てることができます。 – asawyer

+1

@abelenky:それは単に真実ではありません。既に与えられた説明だけでいくつかの解決策を提案することは完全に実現可能です。 –

答えて

3

ファイル名フィールドが静的である場合、あなたはそれプロパティまたはメソッドにし、ゲッターは、それがまだ初期化されていない場合、設定ファイルからそれを初期化する作業を行うことを確認してください可能性が...

そうすればあなたメソッド自体を使ってクラスを明示的に初期化する必要はありません。プロパティ自体にアクセスできるようにすると、値が初期化されます。以下のような

何か..

static string FileName { get { return (_field ?? _field = GetFileName()); } } 

static string GetFileName() { /* TODO: Return filename from config */ } 
+0

これは同じことを達成するための良い方法です。ありがとう。しかし、 '_field'には次のようなエラーが表示されます: '代入の左側は変数、プロパティまたはインデクサーでなければなりません。' – iTSrAVIE

+0

@iTSrAVIE私の例では '_field'の定義は含まれていませんでしたが、値を保持するクラスレベルで定義された' static string'フィールドになります。 。 –

+0

割り当てが余分な括弧を必要とし、問題が解決されました。 __________________________________ 静的な文字列FileName {get {return(_field ?? _field = GetFileName())); }} – iTSrAVIE

0

なぜあなたは静的コンストラクタを使用することはできませんか?

静的メンバーが参照される前にパスを初期化する静的コンストラクターを作成できます。

クラス自体が、私は1時間セッターを使用したい設定にアクセスする方法を知らない場合より多くの情報がhere

0

を見つけることができます:

private static string _filename; 
public static string Filename 
{ 
    get 
    { 
    if(_filename==null) 
     throw new InvalidOperationException("Filename not set"); 
    return _filename; 
    } 
    set 
    { 
    if(_filename!=null) 
     throw new InvalidOperationException("Filename set twice"); 
    _filename=value; 
    } 
} 

やクラスがアクセスできる場合configを直接設定すると、さらに簡単になります。

private static readonly string Filename; 
static MyClassName() 
{ 
    Filename=GetFilenameFromConfig(); 
} 

スタティックコンストラクタで初期化するだけです。

0

構成ファイルのパスがわかっている(つまり、クラスに正式な引数がない)と仮定すると、static constructorが役立ちます。

0

次のようなものから、あなたの現在のクラスを変更することができます: - コードの現在のクライアントは元のメソッド(ハードコード化されたファイル名)を使用し続けることができ

public static Foo 
{ 
    public static void Execute() 
    { 
     Execute("foo.xml"); 
    } 

    public static void Execute(string fileName) 
    { 
     // ... 
    } 
} 

のようなものに

public static Foo 
{ 
    public static void Execute() 
    { 
     const string FileName = "foo.xml"; 
     // ... 
    } 
} 

構成項目としてファイル名を持つ新しいクライアントは、ファイル名をパラメータとして持つ新しいメソッドを使用できます。または、すべてのクライアントが新しいメソッドを使用する必要があると判断した場合は、そのメソッドを変更して古いメソッドを削除できます。

0

最も単純なオプションは、のスタティックコンストラクタを追加することです。それは他のコードの前に実行されます。

public static class Foo 
{ 
    static Foo() 
    { 
     // Initialization code 
    } 

    // Other methods which can depend on initialization code having run 
} 

私が言うように、これは最も簡単である - あなたの既存のコードへの変更の面で。しかし、このようなコードはデバッグが難しい傾向があり、互いに依存する静的コンストラクタがたくさんある場合、(特に循環的な依存関係がある場合は)いくつかのトリッキーな状況に陥る可能性があります。その一例として、"C# Puzzlers" video from NDC 2010 - Eric LippertとNeal Gafterによって与えられた優れた講演を見てください。

関連する問題