T型默认值
T type default value
我有几个扩展方法,例如 ParseInt
、ParseLong
、ParseByte
。现在我正在尝试为所有这些方法制作一个单一的扩展方法。问题是要使 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
,用于 bool
的 false
,以及用于自定义 struct
的这两个规则的组合。
但是:不要这样做。不要创建这个通用方法,因为它只适用于少数精心挑选的类型。作为一般规则,泛型方法适用于 all 类型。 (您可以使用通用参数约束 where T : …
来约束有效类型,但这不会改变基本思想。)
在您的情况下,通用方法仅适用于少数类型,例如 int
、long
、float
、double
、decimal
,等等。您甚至必须已经在泛型方法中检查这些类型,以便您可以遵循正确的方法(int.TryParse
、double.TryParse
等)。这是一个很大的迹象,表明您的方法根本不应该是通用的。
保留您以前的扩展方法 ParseInt
、ParseSingle
、ParseDouble
等。 这是更好的设计。
我有几个扩展方法,例如 ParseInt
、ParseLong
、ParseByte
。现在我正在尝试为所有这些方法制作一个单一的扩展方法。问题是要使 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
,用于bool
的false
,以及用于自定义struct
的这两个规则的组合。
但是:不要这样做。不要创建这个通用方法,因为它只适用于少数精心挑选的类型。作为一般规则,泛型方法适用于 all 类型。 (您可以使用通用参数约束 where T : …
来约束有效类型,但这不会改变基本思想。)
在您的情况下,通用方法仅适用于少数类型,例如 int
、long
、float
、double
、decimal
,等等。您甚至必须已经在泛型方法中检查这些类型,以便您可以遵循正确的方法(int.TryParse
、double.TryParse
等)。这是一个很大的迹象,表明您的方法根本不应该是通用的。
保留您以前的扩展方法 ParseInt
、ParseSingle
、ParseDouble
等。 这是更好的设计。