C# 在应该返回泛型类的方法中返回int
简而言之,我有一个类似这样的方法C# 在应该返回泛型类的方法中返回int,c#,xml,asp.net-mvc,generics,default-value,C#,Xml,Asp.net Mvc,Generics,Default Value,简而言之,我有一个类似这样的方法 public T GetCookie<T>(string key) { T obj; if (typeof(T) == typeof(int)) { return -1; } else { return default(T); } } public T GetCookie(
public T GetCookie<T>(string key)
{
T obj;
if (typeof(T) == typeof(int))
{
return -1;
}
else
{
return default(T);
}
}
public T GetCookie(字符串键)
{
T-obj;
if(typeof(T)=typeof(int))
{
返回-1;
}
其他的
{
返回默认值(T);
}
}
我为什么要这样做?int
的默认值是0
,我需要它是-1
(基于该-1
,我得到了一个巨大的代码示例),所以我想知道是否存在可以更改int
的默认值的东西,或者允许我返回int
,而不是我的泛型类
我现在找不到任何东西:/尝试执行以下操作:
return (T)(object)-1;
不,无法更改默认值。它是编译器在初始化字段时指定的值 您的问题的解决方案完全是基于意见的 如果使用的类型数量有限,则可以使用单独的方法:
public int GetIntCookie(string key)
public string GetStringCookie<T>(string key)
public DateTime GetDateTimeCookie<T>(string key)
public int GetIntCookie(字符串键)
公共字符串GetStringCookie(字符串键)
公共DateTime GetDateTimeCookie(字符串键)
或者,您可以维护默认值的字典:
private static Dictionary<Type, object> = new Dictionary<Type, object>
{
{ typeof(int), -1 },
{ typeof(string), string.Empty },
{ typeof(DateTime), DateTime.MinValue },
}
public T GetCookie<T>(string key)
{
object value;
if (defaultValues.TryGetValue(typeof(T), out value)
{
return (T)value;
}
return default(T);
}
private static Dictionary=新字典
{
{typeof(int),-1},
{typeof(string),string.Empty},
{typeof(DateTime),DateTime.MinValue},
}
公共T GetCookie(字符串键)
{
目标价值;
if(defaultValues.TryGetValue(typeof(T),out值)
{
返回(T)值;
}
返回默认值(T);
}
或者您可以保留您的实现(并修复编译器错误)
public T GetCookie(字符串键)
{
if(typeof(T)=typeof(int))
{
返回(T)(对象)-1;
}
返回默认值(T);
}
正如我在评论中提到的,我总是喜欢使用类型安全性的场景,而不是不使用类型安全性的场景。您实际上希望做的是:
public T GetCookie<T>(string key)
{
return default(T);
}
public int GetCookie<int>(string key)
{
return -1;
}
public T GetCookie(字符串键)
{
返回默认值(T);
}
public int GetCookie(字符串键)
{
返回-1;
}
…不幸的是,这在C#中不起作用(有很好的理由)
如果需要返回字符串,则@xanatos的解决方案是唯一正确的解决方案
但是,如果您不想传递另一个参数,下一个最好的方法是使用重载解析来选择正确的成员:
class SimpleOverloadTest
{
private static T GetCookie<T>(string key, T value)
{
return value;
}
private static int GetCookie(string key, int value)
{
return -1;
}
static void Main()
{
Console.WriteLine(GetCookie("foo", default(int)));
Console.WriteLine(GetCookie("foo", default(float)));
Console.ReadLine();
}
}
类SimpleOverloadTest
{
私有静态T GetCookie(字符串键,T值)
{
返回值;
}
私有静态int GetCookie(字符串键,int值)
{
返回-1;
}
静态void Main()
{
WriteLine(GetCookie(“foo”,默认值(int));
WriteLine(GetCookie(“foo”,默认值(float));
Console.ReadLine();
}
}
请注意,如果添加以下内容,则此操作将不起作用:
private static T GetCookie<T>(string key)
{
return GetCookie(key, default(T));
}
private static T GetCookie(字符串键)
{
返回GetCookie(key,默认值(T));
}
这样做的原因是重载应该在编译时确定,简单地说——在本例中,选择的重载是带有泛型参数的重载——在本例中是错误的重载
通用专业化
我将@xanatos的问题解释为“为什么C#不支持泛型专门化?”.很久以前,我在编译团队的一篇文章中读到过这篇文章,但现在再也找不到了。因此,我会尽我最大的努力…像Eric Lippert这样的人可能会在这个问题上给出比我更好的答案…如下所示:
泛型类型不会在C#编译时进行扩展。方法是作为方法的编译器,具有唯一的标记;基本上,您可以调用方法标记。这是.NET的基础之一:从一开始就为每个方法编译代码。这也意味着重载解析可能发生在“C#编译时”,而不是JIT时,从而使JIT更快
我认为在.NET中不支持泛型专门化的选择主要是(运行时/JIT/编译器)速度的选择
如果要实现泛型重载,我们必须在C编译时存储每个方法令牌的多个方法实现,这将打破上面提到的基础,然后,可以用相同的方法令牌编译每个方法集给不同的(汇编程序)。实现。在这一点上,你必须意识到这会给JIT带来很大的压力:JIT必须执行某种重载解析来选择“正确”的方法;C#编译器可以帮助JIT'ter实现这一点,因为它将简单地生成方法。这本身就是不这样做的一个很好的理由——但让我们继续nue:
具有讽刺意味的是,模板扩展基本上就是它在JIT中的工作方式。如果您有一个值类型,则值类型被放入项“T”,并且方法“真的”被扩展到不同的IL和汇编程序。换句话说,如果您有Foo
,那么Foo
将有不同于Foo
的IL和汇编程序代码。引用类型不是这种情况,因为可以对所有调用进行相同的vtable查找(接口约束)。换句话说,代码是为引用类型
共享的,而不是为值类型
共享的。您实际上可以看到这种情况
通过这样做,您的JIT能够非常快速地生成非常好的代码。因为许多泛型都是引用类型,所以它也从泛化规则中受益匪浅,这使得泛化规则出血速度很快。但是,如果您专门化引用类型,它将破坏这种优化-同样,这也是不这样做的一个很好的理由
<> p>这样,我们就只能在值类型上泛化专门化了。在这一点上,您必须认识到,值类型可以由其他值类型组成,这意味着我们可以递归地组成类型。在C++中,我们把这些东西称为代码>类型列表< /C>(谷歌:模板Meta程序)。
private static T GetCookie<T>(string key)
{
return GetCookie(key, default(T));
}