Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#泛型类型上强制执行任意函数_C#_Generics - Fatal编程技术网

在C#泛型类型上强制执行任意函数

在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.

我正在尝试创建这样一个通用函数,我计划用基本类型实例化它,主要是DateTime、int和string

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));
}