10

タイプセーフな列挙型パターンをジェネリッククラスに実装するにはどうすればよいですか?これらの線に沿って実装されていると仮定しましょう

public class KnownSetting<T>
{
    public readonly static KnownSetting<String> Name = new KnownSetting<String>("name", "Default Name", t => t);
    public readonly static KnownSetting<int> Size = new KnownSetting<String>("size", "25", t => Converter.ToInt32);

    public String Key { get; set; }
    public T DefaultValue { get; set; }
    public Func<String, T> Converter { get; set; }

    private KnownSetting(String key, T defaultValue, Func<String, T> converter)
    {
        Key = key;
        DefaultValue = defaultValue;
        Converter = converter;
    }
}

コンストラクターはプライベートのままなので、パターンの実装はこのように正しいですが、このコンストラクトを使用すると、間違って見えます。

public static class Program
{
    public static void main()
    {
        var x = KnownSetting<?>.Name;
    }
}

次に、KnownSettingコンテナクラスとSetting実装の2つに分割するオプションがありますが、コンストラクタのスコープをプライベートにして、コンテナ内からインスタンス化することはできません。

このパターンを実装して、そのジェネリックの側面をエンドユーザーから隠しておきながら、強く型付けされたままにする方法を教えてください。より適切なパターンがありますか、それともそれを実装するためのより良い方法がありますか?

更新 設定のタイプを一般的なものにしたいことを示すために、2番目のサンプルを追加しました。

4

3 に答える 3

4

別のタイプを使用する基本タイプでヘルパーメソッドを作成し、既知の設定クラスを作成します。基本コンストラクターはSetting(string、object、Func)であるため、Createメソッドが必要です。これが、別のジェネリック変数(U)を導入する理由でもあります。

public class KnownSetting : Setting<object>
{
    private KnownSetting(string key, object defaultValue, Func<string, object> converter) : base(key, defaultValue, converter) { }

    public readonly static Setting<string> Name = Create<string>("name", "Default Name", t => t);
    public readonly static Setting<int> Size = Create<int>("size", 25, t => Convert.ToInt32(t));
}

public class Setting<T>
{
    public string Key { get; set; }
    public T DefaultValue { get; set; }
    public Func<string, T> Converter { get; set; }

    protected static Setting<U> Create<U>(string key, U defaultValue, Func<string, U> converter)
    {
        return new Setting<U>(key, defaultValue, converter);
    }

    protected Setting(string key, T defaultValue, Func<string, T> converter)
    {
        Key = key;
        DefaultValue = defaultValue;
        Converter = converter;
    }
}
public static class Program
{
    static void Main(string[] args)
    {
        var x = KnownSetting.Name;
    }
}
于 2013-01-18T07:34:27.010 に答える
3

新しいクラスで静的データを宣言します。

public class KnownSetting
{
    public readonly static KnownSetting<String> Name = new KnownSetting<String>("name", "Default Name", t => t);
    public readonly static KnownSetting<int> Size = new KnownSetting<String>("size", "25", t => Converter.ToInt32);
}

クラス名は名前とジェネリック型引数の数で一意であるため、C#では同じ名前にすることができます。

于 2013-01-17T18:20:53.723 に答える
0

何かが足りないかもしれませんが、KnownSetting<T>クラスをそのまま使用して、新しいクラスから同じ列挙型インスタンスへの新しい参照を作成してみませんか?何かのようなもの:

public static class KnownSettings {
  public readonly static KnownSetting<string> Name = KnownSetting<string>.Name;
  public readonly static KnownSetting<int> Size = KnownSetting<int>.Size;
  // etc.
}

次に、必要に応じて値を使用できます。

var x = KnownSettings.Name;
于 2013-01-22T08:33:36.450 に答える