如果T没有无参数构造函数,如何从通用方法返回IConvertible?

时间:2016-06-07 20:07:22

标签: c# generics

我有一个自定义类,它读入一组键对值作为实现IConvertible的对象。我想要编写一个通用方法,而不是编写大量的GetValueAsSomeObjectType方法。

我想我几乎已经明白了,但并不完全:

    public static IConvertible GetSetting<T>(string settingName,
        string settingsFile = null, bool
        ignoreCase = true) where T : IConvertible, new()
    {
        IConvertible t = new T();

        foreach (Setting setting in Settings)
        {
            if ((settingsFile == setting.File || settingsFile == null)
                && (settingName == setting.Name
                   || (ignoreCase == true && (settingName.ToLower() == setting.Name.ToLower()))))
            {
                t = (IConvertible)setting.Value;
                return (T)t.ToType(typeof(T), null);
            }
        }

        return t;
    }

现在我似乎能够做到这一点,这很酷:

object KeyName;
bool ValueAsBool = (bool)GetSetting<bool>(nameof(KeyName));

但是,以下结果导致语法错误,因为string没有无参数构造函数:

string ValueAsString = (string)GetSetting<string>(nameof(KeyName));

有关如何使这项工作的任何建议?

2 个答案:

答案 0 :(得分:0)

根据您的方法定义,对我来说最明智的行为似乎是返回硬编码的if(iy != y.end()) return false; if(ix != x.end()) return true; return x <= y; // opposite, see above... if you agree with ascii, use >=, of course 或用户指定的回退值(作为附加参数传入),如果不存在指定名称的设置。无论哪种方式都可以很好地完全避免构建null的问题,允许删除T约束,并允许new()T

即使string编译并且没有抛出异常,构建全新的new T()也不一定是您可以有意义的事情。对于一个简单的示例,如果TT,则某些设置可能需要后备值bool,而其他设置需要后备值false

答案 1 :(得分:0)

@hvd 我能够让它发挥作用!

    public static T GetSetting<T>(string settingName,
        string settingsFile = null, bool
        ignoreCase = true) where T : IConvertible
    {
        foreach (Setting setting in Settings)
        {
            if ((settingsFile == setting.File || settingsFile == null)
                && (settingName == setting.Name
                   || (ignoreCase == true && (settingName.ToLower() == setting.Name.ToLower()))))
            {
                return convertToType<T>(setting.Value);
            }
        }

        return default(T);
    }


    private static T convertToType<T>(IConvertible value) where T : IConvertible
    {
        return (T)value.ToType(typeof(T), null);
    }

    private object value1;
    public bool Value1AsBool = (bool)SettingsReader.GetSetting<bool>(nameof(value1));
    public String Value1AsString = (string)SettingsReader.GetSetting<string>(nameof(value1));

    private object value2;
    public double Value2AsDouble = (double)SettingsReader.GetSetting<double>(nameof(value2));
    public string Value2AsString = (string)SettingsReader.GetSetting<string>(nameof(value2));
    public int Value2AsInt32 = (int)SettingsReader.GetSetting<int>(nameof(value2));