我想创建一个泛型类,其中类的类型可以解析字符串。
我想将这个类用于任何具有静态函数Parse(string)的类, 像System.Int32,System.Double,但也适用于像System.Guid这样的类。它们都具有静态Parse函数
所以我的类需要一个where子句,它将我的泛型类型约束为具有Parse函数的类型
我想像这样使用它:
class MyGenericClass<T> : where T : ??? what to do ???
{
private List<T> addedItems = new List<T>()
public void Add(T item)
{
this.AddedItems.Add(item);
}
public void Add(string itemAsTxt)
{
T item = T.Parse(itemAsTxt);
this.Add(item);
}
}
在where子句中写什么?
答案 0 :(得分:5)
我对使用反射进行解析的答案感到不满意。
我更喜欢类型安全的解决方案,因此编译器会抱怨缺少Parse函数。
通常,您会约束到具有接口的类。但正如其他人所说,没有共同的界面。想一想我不需要接口,我需要一个可以调用的功能
所以我的解决方案是坚持创建者会向Parse函数提供一个委托,该委托将解析字符串以键入T
class MyGenericClass<T>
{
public MyGenericClass(Func<string, T> parseFunc)
{
this.parseFunc = parseFunc;
}
private readonly Func<string, T> parseFunc;
public void Add(string txt)
{
this.Add(parseFunc(txt));
}
}
用法:
MyGenericClass<Guid> x = new MyGenericClass<Guid>(txt => Guid.Parse(txt));
MyGenericClass<int> y = new MyGenericClass<int> (txt => System.Int32.Parse(txt));
答案比我想象的要简单
答案 1 :(得分:1)
我可能会误解你的问题,但是这会解决这个问题吗?
static void Main(string[] args)
{
Guid g = DoParse<Guid>("33531071-c52b-48f5-b0e4-ea3c554b8d23");
}
public static T DoParse<T>(string value)
{
T result = default(T);
MethodInfo methodInfo = typeof(T).GetMethod("Parse");
if (methodInfo != null)
{
ParameterInfo[] parameters = methodInfo.GetParameters();
object classInstance = Activator.CreateInstance(typeof(T), null);
object[] parametersArray = new object[] { value };
result = (T)methodInfo.Invoke(methodInfo, parametersArray);
}
return result;
}
答案 2 :(得分:0)
你根本无法在编译时这样做。除了名字之外,所有这些方法都没有任何。它们既不在任何公共接口中定义,也不具有相同的参数。
想象一下,你有自己的方法,意外地有这个名字,但做了一些完全不同的事情。另外它也是一个实例方法:
class MyType
{
void Parse() { ... }
}
正如您所看到的那样,该方法甚至没有任何参数,因此很难找到 - 例如 - int.Parse(myString)and
myInstanceOfMyType.Parse之间的任何公共逻辑()`。
但即使如果你也能做到。你会对item
做什么?他们之间没有什么共同之处。特别是调用 the methpd是不可能的,因为它们完全不同。
您可以在运行时使用类似的方法循环所有类型:
var types = allAssemblies.SelectMany(x => x.GetTypes())
.Where(x => x.GetMethod("Parse") != null);
但请注意,如果每个类型存在多个带有名称的方法,则会产生AmbiguousMatchException
,这是方法重载的时候。