如何在C#泛型中指定可以从字符串构造的T? (通用类型约束)

时间:2015-03-20 15:31:20

标签: c# .net generics constraints .net-4.5

我想为我的T指定必需的默认构造选项:

  public interface IParameter<T>  /* where T : T(string) */ { 
     T Value { get; set; }
  }

所以我可以从给定的字符串构造它,如果可以这样:

Value  = "bla";

或者至少像这样:

Value = new T("bla");

那么如何在C#泛型中指定可以从字符串构造的T?

4 个答案:

答案 0 :(得分:2)

不幸的是,C#不为泛型参数提供任意构造函数签名限制。仅a restricted number of constraints are supported,其中最接近的一个是new constraint。但是,它仅用于强制执行无参数构造函数。

但是,您可以通过使用带有string并返回T的工厂对象来解决此缺陷。首先,为这样的工厂对象定义一个接口:

public interface IFactory<T>
{
    T Create(string str);
}

随后,您可以在界面中使用该工厂类型:

public interface IParameter<TFactory, T>
    where TFactory : IFactory<T>
{ 
    T Value { get; set; }
}

如果您希望能够随意实例化工厂,可以要求它们具有无参数构造函数:

public interface IParameter<TFactory, T>
    where TFactory : new(), IFactory<T>
{ 
    T Value { get; set; }
}

然后,您可以使用通用方法基于T实例化string,例如作为界面的扩展方法:

public static class ParameterUtilities
{
    public static void AssignValue<TFactory, T>(this IParameter<TFactory, T> prm, string str)
        where TFactory : new(), IFactory<T>
    {
        var factory = new TFactory();
        prm.Value = factory.Create(str);
    }
}

作为如何使用它的一个例子,我们假设变量myPrm是一个实例,用适当的类型参数实现你的IParameter接口。然后你可以调用这样的东西:

myPrm.AssignValue("Hello, World!");

答案 1 :(得分:1)

你不能,因为在泛型类型约束中,你不能说类型必须有一个特定的构造函数(只有它必须有一个无参数构造函数),也不能说它必须有特定的方法/运算符

BUT

public interface IFromString<T>
{
    void DeserializeFromString(string str);
}

public class MyType : IFromString<MyType>
{
    public int Value;

    public void DeserializeFromString(string str)
    {
        Value = int.Parse(str);
    }
}

public interface IParameter<T> where T : IFromString<T>, new()
{
    T Value { get; set; }
}

public class Parameter<T> : IParameter<T> where T : IFromString<T>, new()
{
    T Value { get; set; }

    public void Load(string str)
    {
        Value = new T();
        Value.DeserializeFromString(str);
    }
}

一个经典的例子......一个接口,表明一个类型可以从(某些)反序列化(xml经常:-))

使用:

Parameter<MyType> parameter = new Parameter<MyType>();
parameter.Load(someStringLoadedFromSomewhere);

答案 2 :(得分:1)

不幸的是,这种限制是不合法的。只允许无参数构造函数约束:

where T : new()

答案 3 :(得分:0)

您无法在界面中指定构造函数。根据您的要求,您可以使用抽象类:

伪代码不在VS的机器上:

public abstract class BaseParameter<T>
{ 
    public abstract void BaseParameter(string something);

    T Value { get; set; }
}