我有一个类似
的扩展方法public static T ThrowIfObjectIsNull<T>(this T argument) where T : class
{
if (argument == null)
throw new ArgumentNullException(nameof(argument));
return argument;
}
这基本上检查传递的对象是否为空。我想要做的是创建另一个扩展方法,其中传入的int
值不是0.所以我继续创建:
public static T ThrowIfZero<T>(this T argument) where T : struct
{
if (argument == 0)
throw new ArgumentOutOfRangeException("some error here");
return argument;
}
当然上面没有编译提示错误:
错误CS0019运算符'=='无法应用于'T'和'int'类型的操作数
有人能指出我如何检查参数值是否不是0
的正确方向吗?
答案 0 :(得分:23)
您可以简单地使用Equals
:
public static T ThrowIfZero<T>(this T argument) where T : struct
{
if (argument.Equals(0))
throw new ArgumentOutOfRangeException("some error here");
return argument;
}
但如果参数是例如十进制0.0m
并且不等于Peter已正确评论的整数0
,那么这将无法正常工作。
因此,如果您想要一个适用于任何数字的版本,您可以使用此方法:
public static T ThrowIfZero<T>(this T argument) where T : struct
{
bool isZero = Decimal.Compare(0.0m, Convert.ToDecimal(argument)) == 0;
if (isZero)
throw new ArgumentOutOfRangeException("some error here");
return argument;
}
答案 1 :(得分:12)
您也可以使用EqualityComparer。
public static T ThrowIfZero<T>(this T argument) where T : struct
{
if (EqualityComparer<T>.Default.Equals(argument, default(T)))
throw new ArgumentOutOfRangeException("some error here");
return argument;
}
你可以参考这个post的答案(信用证应该转到@Mehrdad)。
答案 2 :(得分:4)
看起来你根本不需要泛型。如果变量只是你建议的int,只需使用:
public static int ThrowIfZero(this int argument)
{
if (argument == 0)
{
throw new ArgumentOutOfRangeException("some error here");
}
return argument;
}
答案 3 :(得分:1)
int
,decimal
等实施IComparable
,所以这样的事情也有效:
public static T ThrowIfZero<T>(this T argument)
where T : struct, IComparable
{
if (argument.CompareTo(default(T)) == 0)
throw new ArgumentOutOfRangeException("some error here");
return argument;
}
答案 4 :(得分:0)
我最近看到的另一种方式:
public static int ThrowIfZero<T>(this T param)
where T : struct
{
var o = (object)param;
int i;
try { i = (int)o; }
catch { throw new ArgumentException("Param must be of type int"); }
if (i == 0) throw new ArgumentException("Must be not be zero");
return (int)(object)param;
}
我们可以欺骗编译器让我们先将T
转换为int
,然后再将其object
强制转换为int
。这适用于int
,但缺点是它仅适用于float
,不适用于public static T ThrowIfZero<T>(this T param)
where T : struct
{
switch (param)
{
case int i: if (i == 0) throwException(); break;
case double d: if (d == 0) throwException(); break;
case float f: if (f == 0) throwException(); break;
case decimal c: if (c == 0) throwException(); break;
case long l: if (l == 0) throwException(); break;
case uint ui: if (ui == 0) throwException(); break;
case ulong ul: if (ul == 0) throwException(); break;
case byte b: if (b == 0) throwException(); break;
default: throw new ArgumentException("Invalid Type");
}
return param;
// ---- Local Functions ---- //
void throwException() => throw new ArgumentException("Must not be zero");
}
。
如果您希望它适用于所有可数类型,您可以使用模式匹配并执行以下操作:
where T : numeric
当然,最好的解决方案是,如果他们把Jon Skeet放在他的报价上并做了一个ComplexNumber
,它基本上限制了上面的类型,也许是一些自定义类型,所以我们可以包括我们自己的SuperBigInteger
或switch
。
说实话,我不会这样做,因为第一种方式是铸造,第二种方式只是导致缺失的情况,如果你需要,必须维持NA
,只是想到不过,我会展示更多选项。