我有一个泛型类,我需要约束只有值类型(int,float等)。我有一个方法,根据类型的测试调用Parse方法。例如:
class MyClass<T>
{
...
private static T ParseEntry(string entry)
{
if(typeof(T) == typeof(float))
{
return (T) float.Parse(entry);
}
if(typeof(T) == typeof(int))
{
.... you get the idea
}
}
}
将T约束到struct
不起作用,如果可能的话我真的想避免装箱/拆箱。有什么想法吗?
编辑:更深入地了解这一点。我注意到在库中我正在开发两个类具有非常相似的属性/方法等。唯一的区别是基础类型的数据(int或float)。这引出了我的泛型设计。唯一的挂起是因为调用特定的Parse方法取决于它是float还是int。我可以用拳击/拆箱来解决这个问题,但如果可能的话我真的想避免这种情况。
答案 0 :(得分:11)
private static T ParseEntry(string entry)
{
TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
return (T) conv.ConvertFromString(entry);
}
具有使用类型转换器处理任何类型的优点(或者您可以在运行时添加自己的类型转换器)。它确实有拳击,但真的,it isn't so bad。如果那是你最大的问题,那你就是错误的做法。
答案 1 :(得分:5)
不幸的是,您无法创建描述类型的约束。你不能写,例如:
class MyClass<T> where T : int { ... } // won't compile
您可能最好将约束保留为struct
,但添加一些运行时检查以确保在实例化类时T只是受支持的类型之一。既然你没有多说你打算如何使用你的课程 - 很难提供关于如何实现更好的类型安全的替代设计建议。
编辑:您应该查看Marc和其他人推荐的类型转换器选项。这似乎是要走的路。
编辑:我想到的一个可能的想法是让Parse()
方法实际上成为委托:Func<string,T>
- 您在构建期间分配。这将使您能够:
以下是我的意思的代码示例:
class MyClass<T>
{
private readonly Func<string,T> ParseEntry;
public MyClass( Func<string,T> parser )
{
ParseEntry = parser;
}
}
public static class AvailableParsers
{
public static Func<string,int> ParseInt = s => int.Parse( s );
public static Func<string,float> ParseFloat = s => float.Parse(s);
}
您可以阅读available constraints here。唯一可用的限制是:
答案 2 :(得分:5)
愚蠢也许,但是 - 如果你在谈论一组有限的类型,你为什么不重载这个方法呢?像*Writer.Write()
方法一样,每个“基础”类型都有重载?
简而言之:为什么是泛型的,如果你根据类型做了不同的事情(这会以某种方式违背为传递任何类型做同样事情的目的)?
编辑:考虑使用情况我认为您可能实际上想要使用Convert.ChangeType。
这样的事情:
class MyClass<T> where T: IConvertible
{
private static T ParseEntry(string entry)
{
return (T)Convert.ChangeType(entry, typeof(T));
}
}
答案 3 :(得分:1)
我想我没有看到这里的价值......为什么不使用Convert类?
答案 4 :(得分:0)
另外,想象一下你不必处理原始类型,但是你真的想处理所有结构 - 它仍然是不可能的,因为结构不能保证实现一个(迄今为止想象的)接口IParsable
被投入T。