我正在开展一个项目,我发现我正在很多很多地方检查以下内容:
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);
}
有更好的方法吗?
答案 0 :(得分:133)
我喜欢if ((item.Rate ?? 0) == 0) { }
更新1:
您还可以定义一个扩展方法,如:
public static bool IsNullOrValue(this double? value, double valueToCheck)
{
return (value??valueToCheck) == valueToCheck;
}
并像这样使用它:
if(item.IsNullOrValue(0)){}
//但你从中得不到多少
答案 1 :(得分:39)
使用泛型:
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
,假设是双倍,default(t)
是0d,bool是false
,char是'\0'
等等......
答案 2 :(得分:26)
虽然我非常喜欢接受的答案,但我认为,为了完整起见,还应提及此选项:
if (item.Rate.GetValueOrDefault() == 0) { }
此解决方案
((item.Rate ?? 0) == 0)
更容易阅读(这可能只是一种品味问题)。¹这不应该影响你的决定,因为这些微观优化不太可能产生任何影响。
答案 3 :(得分:17)
这实际上仅仅是使用泛型扩展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));
}
注意我们不需要检查null(T)是否为null,因为我们正在处理值类型或结构!这也意味着我们可以安全地假设T valueToCheck不会为空;记得这里T?是简写Nullable&lt; T&gt;所以通过将扩展名添加到Nullable&lt; T&gt;我们在int?,double ?, bool中得到方法?等
<强>示例:强>
double? x = null;
x.IsNullOrDefault(); //true
int? y = 3;
y.IsNullOrDefault(); //false
bool? z = false;
z.IsNullOrDefault(); //true
答案 4 :(得分:2)
我同意使用??运营商。
如果你正在处理字符串,请使用if(String.IsNullOrEmpty(myStr))
答案 5 :(得分:2)
您的代码示例将失败。如果obj为null,则obj.ToString()将导致空引用异常。我会在你的辅助函数开始时简化过程并检查一个null obj。至于你的实际问题,你检查null或零的类型是什么?在String上有一个很好的IsNullOrEmpty函数,在我看来,这将是一个很好的使用扩展方法在int上实现一个IsNullOrZero方法?类型。
编辑:记住,'?'只是INullable类型的编译器糖,所以你可以把一个INullable作为parm,然后jsut将它与null(parm == null)进行比较,如果不是null则比较为零。
答案 6 :(得分:2)
有更好的方法吗?
好吧,如果你真的在寻找更好的方法,你可以在Rate之上添加另一层抽象。 好吧,我刚才想到了Nullable Design Pattern。
using System; using System.Collections.Generic; namespace NullObjectPatternTest { public class Program { public static void Main(string[] args) { var items = new List { new Item(RateFactory.Create(20)), new Item(RateFactory.Create(null)) }; PrintPricesForItems(items); } private static void PrintPricesForItems(IEnumerable items) { foreach (var item in items) Console.WriteLine("Item Price: {0:C}", item.GetPrice()); } } public abstract class ItemBase { public abstract Rate Rate { get; } public int GetPrice() { // There is NO need to check if Rate == 0 or Rate == null return 1 * Rate.Value; } } public class Item : ItemBase { private readonly Rate _Rate; public override Rate Rate { get { return _Rate; } } public Item(Rate rate) { _Rate = rate; } } public sealed class RateFactory { public static Rate Create(int? rateValue) { if (!rateValue || rateValue == 0) return new NullRate(); return new Rate(rateValue); } } public class Rate { public int Value { get; set; } public virtual bool HasValue { get { return (Value > 0); } } public Rate(int value) { Value = value; } } public class NullRate : Rate { public override bool HasValue { get { return false; } } public NullRate() : base(0) { } } }
答案 7 :(得分:0)
public static bool nz(object obj)
{
return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}
答案 8 :(得分:0)
class Item{
bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}
答案 9 :(得分:0)
不要忘记,对于字符串,您始终可以使用:
String.IsNullOrEmpty(str)
而不是:
str==null || str==""
答案 10 :(得分:-1)
距离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));
}
}