如何在 C# 泛型中指定可以从字符串构造的 T ? (通用类型约束)
How to specify in C# generics such T that is constructible from string? (generic type constraint)
我想为我的 T 指定必需的默认构造选项:
public interface IParameter<T> /* where T : T(string) */ {
T Value { get; set; }
}
所以我可以从给定的字符串构造它,如果像这样:
Value = "bla";
或者至少像这样:
Value = new T("bla");
那么如何在 C# 泛型中指定可以从字符串构造的 T 呢?
你不能,因为在泛型类型约束中你不能说类型必须有一个特定的构造函数(只能说它必须有一个无参数的构造函数)也不能说它必须有特定的 methods/operators .
但是
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);
不幸的是,该限制是不合法的。只允许无参数构造函数约束:
where T : new()
您不能在接口中指定构造函数。根据您的要求,您可以使用摘要 class:
伪代码不在带有 VS 的机器上:
public abstract class BaseParameter<T>
{
public abstract void BaseParameter(string something);
T Value { get; set; }
}
遗憾的是,C# 不为泛型参数提供任意构造函数签名限制。只有 a restricted number of constraints are supported, the closest one of which is the new
constraint。但是,它仅用于强制执行无参数构造函数。
但是,您可以通过使用带有 string
和 returns 和 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; }
}
然后,您可以使用通用方法根据 string
实例化 T
,例如作为接口的扩展方法:
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!");
我想为我的 T 指定必需的默认构造选项:
public interface IParameter<T> /* where T : T(string) */ {
T Value { get; set; }
}
所以我可以从给定的字符串构造它,如果像这样:
Value = "bla";
或者至少像这样:
Value = new T("bla");
那么如何在 C# 泛型中指定可以从字符串构造的 T 呢?
你不能,因为在泛型类型约束中你不能说类型必须有一个特定的构造函数(只能说它必须有一个无参数的构造函数)也不能说它必须有特定的 methods/operators .
但是
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);
不幸的是,该限制是不合法的。只允许无参数构造函数约束:
where T : new()
您不能在接口中指定构造函数。根据您的要求,您可以使用摘要 class:
伪代码不在带有 VS 的机器上:
public abstract class BaseParameter<T>
{
public abstract void BaseParameter(string something);
T Value { get; set; }
}
遗憾的是,C# 不为泛型参数提供任意构造函数签名限制。只有 a restricted number of constraints are supported, the closest one of which is the new
constraint。但是,它仅用于强制执行无参数构造函数。
但是,您可以通过使用带有 string
和 returns 和 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; }
}
然后,您可以使用通用方法根据 string
实例化 T
,例如作为接口的扩展方法:
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!");