使用泛型键入安全枚举模式实现

时间:2013-01-17 16:56:51

标签: c# design-patterns generics enums type-safety

如何在泛型类上实现类型安全枚举模式?让我们假设它是按照这些方式实施的

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实现,但是构造函数的范围不能是私有的,以便从容器中实例化。

如何实现这种模式,以便它的泛型方面隐藏在最终用户之外,但仍保持强类型?是否有更合适的模式,还是有更好的方法来实现它?

更新 我添加了第二个示例来说明我确实希望设置的类型是通用的。

3 个答案:

答案 0 :(得分:4)

在基类型中创建一个使用其他类型的辅助方法,并创建一个已知的设置类。您需要Create方法,因为基本构造函数是Setting(string,object,Func)。这也是我引入另一个通用变量(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;
    }
}

答案 1 :(得分: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#中可以具有相同的名称,因为类名在名称和泛型类型参数计数上是唯一的。

答案 2 :(得分: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;