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