在C#泛型类型上强制执行任意函数
我正在尝试创建这样一个通用函数,我计划用基本类型实例化它,主要是DateTime、int和string在C#泛型类型上强制执行任意函数,c#,generics,C#,Generics,我正在尝试创建这样一个通用函数,我计划用基本类型实例化它,主要是DateTime、int和string static T MyParameter<T>(string value, T defaultValue) { return value.StartsWith("$$") ? defaultValue : T.Parse(value); } 静态T MyParameter(字符串值,T defaultValue) { 返回值.StartsWith(“$$”)?默认值:T.
static T MyParameter<T>(string value, T defaultValue)
{
return value.StartsWith("$$") ? defaultValue : T.Parse(value);
}
静态T MyParameter(字符串值,T defaultValue)
{
返回值.StartsWith(“$$”)?默认值:T.Parse(value);
}
这不会编译,因为不能保证t会有“Parse”
是否有一种“直接”的方式来实施它?(我的意思是,避免反思或委托他人做脏活)
我找不到任何对t的约束可以起作用。您可以为泛型案例传入parse方法:
static T MyParameter<T>(string value, T defaultValue, Func<string, T> parse)
{
return value.StartsWith("$$") ? defaultValue : parse(value);
}
如果你真的不喜欢这个,你可以使用反射,尽管我不推荐:
static T MyParameter<T>(string value, T defaultValue)
{
if (value.StartsWith("$$"))
{
return defaultValue
}
var method = typeof(T).GetMethod("Parse", new[] { typeof(string) });
return (T)method.Invoke(null, new[] { value });
}
静态T MyParameter(字符串值,T defaultValue)
{
if(value.StartsWith(“$$”)
{
返回默认值
}
var method=typeof(T).GetMethod(“Parse”,new[]{typeof(string)});
return(T)method.Invoke(null,new[]{value});
}
这应该可以做到:
static T MyParameter<T>(string value, T defaultValue)
{
return (T) (value.StartsWith("$$") ? defaultValue : Convert.ChangeType(value, typeof (T)));
}
静态T MyParameter(字符串值,T defaultValue)
{
return(T)(value.StartsWith(“$$”)?默认值:Convert.ChangeType(value,typeof(T));
}
在泛型上使用约束怎么样
因此,您的方法变成:
static T MyParameter<T>(string value, T defaultValue) where T : IParseable
{
return (T)(value.StartsWith("$$") ? defaultValue : defaultValue.Parse(value));
}
static T MyParameter(字符串值,T defaultValue),其中T:IParseable
{
return(T)(value.StartsWith(“$$”)?defaultValue:defaultValue.Parse(value));
}
当然,这意味着使用的所有类型都必须实现IParseable。恐怕没有。我的一般方法是将
t
约束为IConverible
,并使用Convert.ChangeType
和cast来处理此问题。但是,如果您的值以$$开头,它几乎总是无法解析,除非您去掉美元符号。@vcsjones我想这就是当value
以$
开头时他返回defaultValue
的原因。我改变了我的想法。是的,这很有道理。这是正确的方法。基本上,您需要使用类型的协方差来确保它符合您试图调用的内容。这实际上不会编译。1) 您试图在T
上静态调用Parse
,2)除非IParseable
是通用的(例如其中T:IParseable
),否则Parse
的返回值不需要强制转换就无法返回,3)即使您修复了这些问题,您仍然无法使用.NET提供的内置数据类型(int
,DateTime
,string
)调用此函数,因为它们没有实现自定义的IParseable
接口。是的,您是对的,p.s.w.g.I fixed#1和#2#3.你说得对。这就是这段代码的问题所在。基本上,您必须为所有基本数据类型编写包装,这很烦人。您仍然没有修复#2。如果IParseable
不是通用接口,它的返回类型将类似于object
,因此您必须将其转换为返回值才能返回它。如果它是泛型的,则必须在约束中指定它。另外,现在您已经更正了#1,您必须处理defaultValue
可能为空的可能性。对不起,如果我好像在吹毛求疵。这是一种有效的方法,但我认为如果没有一个有效的示例,这只会造成更多的混乱。注意:如果您在字典中按T
的每个值缓存method
,反射实际上会快一些。当然,基本类型都实现了IConvertible
。
static T MyParameter<T>(string value, T defaultValue) where T : IParseable
{
return (T)(value.StartsWith("$$") ? defaultValue : defaultValue.Parse(value));
}