可空类型:在 c# 中检查空或零的更好方法
Posted
技术标签:
【中文标题】可空类型:在 c# 中检查空或零的更好方法【英文标题】:Nullable types: better way to check for null or zero in c# 【发布时间】:2010-10-12 14:36:06 【问题描述】:我正在做一个项目,我发现我在很多很多地方检查以下内容:
if(item.Rate == 0 || item.Rate == null)
更多的是好奇,检查这两种情况的最佳方法是什么?
我添加了一个辅助方法:
public static bool nz(object obj)
var parsedInt = 0;
var parsed = int.TryParse(obj.ToString(), out parsedInt);
return IsNull(obj) || (parsed && parsedInt == 0);
有没有更好的办法?
【问题讨论】:
【参考方案1】:C#9 : 你可以写
if (item.Rate is null or 0)
【讨论】:
【参考方案2】:比Joshua Shannon 的漂亮answer 更进一步。现在防止boxing/unboxing:
public static class NullableEx
public static bool IsNullOrDefault<T>(this T? value)
where T : struct
return EqualityComparer<T>.Default.Equals(value.GetValueOrDefault(), default(T));
【讨论】:
【参考方案3】:别忘了,对于字符串,你总是可以使用:
String.IsNullOrEmpty(str)
代替:
str==null || str==""
【讨论】:
问题与“0”而不是空字符串进行比较。【参考方案4】:虽然我非常喜欢接受的答案,但我认为,为了完整起见,也应该提到这个选项:
if (item.Rate.GetValueOrDefault() == 0)
这个解决方案
不需要其他方法, 比所有其他选项都快,因为GetValueOrDefault is a single field read operation¹ 和 比((item.Rate ?? 0) == 0)
更容易阅读(不过这可能是个人喜好问题)。
¹但这不应该影响您的决定,因为这些类型的微优化不太可能产生任何影响。
【讨论】:
【参考方案5】:我喜欢if ((item.Rate ?? 0) == 0)
更新 1:
您还可以定义一个扩展方法,例如:
public static bool IsNullOrValue(this double? value, double valueToCheck)
return (value??valueToCheck) == valueToCheck;
并像这样使用它:
if(item.IsNullOrValue(0))
// 但你并没有从中得到什么
【讨论】:
谢谢 - 非常简洁!我担心可读性,但得出的结论是,如果我真正理解了 ??运算符。 你应该使用扩展方法;虽然在编写时它是可读的,但这个小代码块需要一点点思考,这意味着如果你尝试阅读代码并使用它 - 你会从主要问题上分心。 @nailitdown:不是真的,你只需要一个 Nullable这实际上只是 Freddy Rios 接受的答案的扩展,仅使用泛型。
public static bool IsNullOrDefault<T>(this Nullable<T> value) where T : struct
return default(T).Equals( value.GetValueOrDefault() );
public static bool IsValue<T>(this Nullable<T> value, T valueToCheck) where T : struct
return valueToCheck.Equals((value ?? valueToCheck));
注意我们不需要检查 default(T) 是否为 null,因为我们正在处理值类型或结构!这也意味着我们可以安全地假设 T valueToCheck 不会为空;记得这里那个T吗?是 Nullable
示例:
double? x = null;
x.IsNullOrDefault(); //true
int? y = 3;
y.IsNullOrDefault(); //false
bool? z = false;
z.IsNullOrDefault(); //true
【讨论】:
【参考方案7】:您的代码示例将失败。如果 obj 为 null,则 obj.ToString() 将导致 null 引用异常。我会缩短该过程并在您的辅助函数开始时检查 null obj。至于您的实际问题,您要检查的类型是 null 还是零?在 String 上有一个很棒的 IsNullOrEmpty 函数,在我看来这将是一个很好的使用扩展方法来在 int 上实现 IsNullOrZero 方法?输入。
编辑:记住,“?”只是 INullable 类型的编译器糖,因此您可能将 INullable 作为参数,然后将其与 null (parm == null) 进行比较,如果不是 null,则与零进行比较。
【讨论】:
为捕获该错误而欢呼 - 在这个项目中,我需要检查 int?、double?、decimal? 等,这就是我使用“object”的原因 记住,'?'只是 INullable有没有更好的方法?
好吧,如果您真的在寻找更好的方法,您可能可以在 Rate 之上添加另一层抽象。 好吧,这是我刚刚想出的使用 Nullable 设计模式。
使用系统; 使用 System.Collections.Generic; 命名空间 NullObjectPatternTest 公开课程序 公共静态无效主要(字符串[]参数) var items = 新列表 新项目(RateFactory.Create(20)), 新项目(RateFactory.Create(空)) ; PrintPricesForItems(项目); 私有静态无效 PrintPricesForItems(IEnumerable 项目) foreach (var item in items) Console.WriteLine("商品价格:0:C", item.GetPrice()); 公共抽象类 ItemBase 公共抽象费率得到; 公共 int GetPrice() // 无需检查 Rate == 0 或 Rate == null 返回 1 * Rate.Value; 公共类项目:ItemBase 私有只读速率_Rate; 公共覆盖率率 得到 返回 _Rate; 公共项目(费率) _Rate = 费率; 公共密封类 RateFactory 公共静态速率创建(int?rateValue) 如果 (!rateValue || rateValue == 0) 返回新的 NullRate(); 返回新的速率(rateValue); 公开课率 公共 int 值 获取;放; public virtual bool HasValue get return (Value > 0); 公共利率(整数值)价值=价值; 公共类 NullRate : 率 公共覆盖 bool HasValue get return false; 公共 NullRate() : 基数(0)【讨论】:
我认为你是对的,在早期阶段消除空值是可行的方法 不完全是。有一个概念叫做“重构”。您可以将代码重构为更好的模式或更好的结构。您始终可以在以后的阶段消除可为空的值。【参考方案9】:使用泛型:
static bool IsNullOrDefault<T>(T value)
return object.Equals(value, default(T));
//...
double d = 0;
IsNullOrDefault(d); // true
MyClass c = null;
IsNullOrDefault(c); // true
如果T
是一个引用类型,value
将与null
(default(T)
)进行比较,否则,如果T
是一个value type
,假设是double , default(t)
是 0d,bool 是 false
,char 是 '\0'
等等...
【讨论】:
扩展方法:public static bool IsNullOrValue<T>(this T? value, T valueToCheck) where T : struct return (value ?? default(T)).Equals(valueToCheck);
我喜欢这个解决方案的清洁度。请记住 default(int?)
是 null
而不是 0
但是。所有可为空的值(整数)类型的默认值为 null,如果在此方法中传递 0,则将返回 false。见:docs.microsoft.com/en-us/dotnet/csharp/language-reference/…【参考方案10】:
class Item
bool IsNullOrZero getreturn ((this.Rate ?? 0) == 0);
【讨论】:
您的解决方案适用于一个属性,我应该指定我有许多相同项目的属性来检查空/零【参考方案11】:我同意使用 ??操作员。
如果您正在处理字符串,请使用 if(String.IsNullOrEmpty(myStr))
【讨论】:
【参考方案12】:public static bool nz(object obj)
return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
【讨论】:
反射是慢,小心这样的解决方案。我不反对反射,但我不希望它出现在像这样的“简单”函数中,它会让我措手不及。 这实际上检查为零吗? 其实,没有。我相信 Activator.CreateInstance(obj.GetType()) 将为可为空的类型返回 null。 @configurator:当可空类型被装箱时,它们被装箱为底层结构,也就是说,这不会构造一个可以为空的空值,而是一个默认值不可为空的结构。以上是关于可空类型:在 c# 中检查空或零的更好方法的主要内容,如果未能解决你的问题,请参考以下文章