T型默认值

T type default value

我有几个扩展方法,例如 ParseIntParseLongParseByte。现在我正在尝试为所有这些方法制作一个单一的扩展方法。问题是要使 Default 参数可选,我必须给它一个像 T Default = 0 这样的值,但它会生成错误:

A value of type 'int' cannot be used as a default parameter because there are no standard conversions to type 'T'

如果我像T Default = (T)0那样使用它,那么我会得到另一个错误:

Cannot convert type 'int' to 'T'

这是我的扩展方法:

public static T Parse<T>(this string x, T Default = 0)
        {
            Type type = typeof(T);
            if(type == typeof(int))
            { if(!string.IsNullOrEmpty(x) int.TryParse(x , out Defualt); return Default;  }
        }

您可以只使用 default(T) 来代替:

public static T Parse<T>(this string x, T defaultValue = default(T))

但是,我强烈质疑此处的设计 - 您实际上并不是在编写通用方法,而是一种接受一组特定类型并以不同方式对待每个类型的方法。有时这是对你强制执行的,但我通常会有一个 Dictionary<T, SomeDelegate> 来尝试更干净地处理它。

此外,您在调用 int.TryParse 时仍然会遇到问题 - 您不能将 Parse<T> 的参数用作参数 - 您需要这样的东西:

if (typeof(T) == typeof(int))
{
    // You need to consider what you want to happen if
    // int.TryParse returns false - do you want to return 0,
    // or defaultValue?
    int ret;
    if (int.TryParse(x, out ret))
    {
        // Annoying but required due to which conversions are available
        return (T)(object) ret;
    }
}
return defaultValue;

就像已经提到的另一个答案一样,您可以使用 default 关键字获取泛型类型的默认值作为编译时常量:在您的情况下为 default(T)

  • 如果 T 是 class 或接口类型,default(T) 是空引用。
  • 如果 T 是一个结构,那么 default(T) 是所有位都为零的值。这是用于数字类型的 0,用于 boolfalse,以及用于自定义 struct 的这两个规则的组合。

但是:不要这样做。不要创建这个通用方法,因为它只适用于少数精心挑选的类型。作为一般规则,泛型方法适用于 all 类型。 (您可以使用通用参数约束 where T : … 来约束有效类型,但这不会改变基本思想。)

在您的情况下,通用方法仅适用于少数类型,例如 intlongfloatdoubledecimal,等等。您甚至必须已经在泛型方法中检查这些类型,以便您可以遵循正确的方法(int.TryParsedouble.TryParse 等)。这是一个很大的迹象,表明您的方法根本不应该是通用的。

保留您以前的扩展方法 ParseIntParseSingleParseDouble 等。 这是更好的设计。