可空类型:在 c# 中检查空值或零的更好方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/633286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 11:07:17  来源:igfitidea点击:

Nullable types: better way to check for null or zero in c#

c#nullzero

提问by nailitdown

I'm working on a project where i find i'm checking for the following in many, many places:

我正在做一个项目,我发现我在很多地方检查以下内容:

if(item.Rate == 0 || item.Rate == null) { }

more as a curiousity than anything, what's the best way to check for both cases?

更令人好奇的是,检查这两种情况的最佳方法是什么?

I've added a helper method which is:

我添加了一个辅助方法,它是:

public static bool nz(object obj)
{
    var parsedInt = 0;
    var parsed = int.TryParse(obj.ToString(), out parsedInt);
    return IsNull(obj) || (parsed && parsedInt == 0);
}

Is there a better way?

有没有更好的办法?

采纳答案by eglasius

I like if ((item.Rate ?? 0) == 0) { }

我喜欢 if ((item.Rate ?? 0) == 0) { }

Update 1:

更新 1:

You could also define an extension method like:

您还可以定义一个扩展方法,如:

public static bool IsNullOrValue(this double? value, double valueToCheck)
{
    return (value??valueToCheck) == valueToCheck;
}

And use it like this:

并像这样使用它:

if(item.IsNullOrValue(0)){}// but you don't get much from it

if(item.IsNullOrValue(0)){}// 但你并没有从中得到太多

回答by eglasius

public static bool nz(object obj)
{
    return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}

回答by Nick Josevski

I agree with using the ?? operator.

我同意使用 ?? 操作员。

If you're dealing with strings use if(String.IsNullOrEmpty(myStr))

如果您正在处理字符串,请使用 if(String.IsNullOrEmpty(myStr))

回答by Walden Leverich

You code sample will fail. If obj is null then the obj.ToString() will result in a null reference exception. I'd short cut the process and check for a null obj at the start of your helper function. As to your actual question, what's the type you're checking for null or zero? On String there's a great IsNullOrEmpty function, seems to me this would be a great use of extension methods to implement an IsNullOrZero method on the int? type.

您的代码示例将失败。如果 obj 为空,则 obj.ToString() 将导致空引用异常。我会缩短该过程并在您的辅助函数开始时检查空 obj。至于您的实际问题,您要检查 null 或零的类型是什么?在 String 上有一个很棒的 IsNullOrEmpty 函数,在我看来这会很好地使用扩展方法来在 int 上实现 IsNullOrZero 方法?类型。

Edit: Remember, the '?' is just compiler sugar for the INullable type, so you could probably take an INullable as the parm and then jsut compare it to null (parm == null) and if not null compare to zero.

编辑:记住,'?' 只是 INullable 类型的编译器糖,因此您可以将 INullable 作为参数,然后将其与 null (parm == null) 进行比较,如果不是 null,则与零进行比较。

回答by dtroy

class Item{  
 bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}

回答by CMS

Using generics:

使用泛型:

static bool IsNullOrDefault<T>(T value)
{
    return object.Equals(value, default(T));
}

//...
double d = 0;
IsNullOrDefault(d); // true
MyClass c = null;
IsNullOrDefault(c); // true

If Tit's a reference type, valuewill be compared with null( default(T)), otherwise, if Tis a value type, let's say double, default(t)is 0d, for bool is false, for char is '\0'and so on...

如果T引用类型value将与null( default(T))进行比较,否则,如果T是 a value type,比方说 double,default(t)是 0d,对于 bool 是false,对于 char 是'\0'等等......

回答by dance2die

is there a better way?

有没有更好的办法?

Well, if you are really looking for a better way, you can probably add another layer of abstraction on top of Rate. Well here is something I just came up with using Nullable Design Pattern.

好吧,如果你真的在寻找更好的方法,你可以在 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) { }
    }
}

回答by Chris

Don't forget, for strings, you can always use:

不要忘记,对于字符串,您始终可以使用:

String.IsNullOrEmpty(str)

Instead of:

代替:

str==null || str==""

回答by Joshua Shannon

This is really just an expansion of Freddy Rios' accepted answer only using Generics.

这实际上只是 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));
}

NOTEwe don't need to check default(T) for null since we are dealing with either value types or structs! This also means we can safely assume T valueToCheck will not be null; Remember here that T? is shorthand Nullable<T> so by adding the extension to Nullable<T> we get the method in int?, double?, bool? etc.

注意我们不需要检查 default(T) 是否为 null,因为我们正在处理值类型或结构!这也意味着我们可以安全地假设 T valueToCheck 不会为空;还记得这里的那个 T 吗?是简写 Nullable<T> 所以通过向 Nullable<T> 添加扩展,我们得到了 int?, double?, bool? 中的方法。等等。

Examples:

例子:

double? x = null;
x.IsNullOrDefault(); //true

int? y = 3;
y.IsNullOrDefault(); //false

bool? z = false;
z.IsNullOrDefault(); //true

回答by Heinzi

Although I quite like the accepted answer, I think that, for completeness, this option should be mentioned as well:

虽然我很喜欢接受的答案,但我认为,为了完整性,还应该提到这个选项:

if (item.Rate.GetValueOrDefault() == 0) { }

This solution

这个解决方案



1 This should not influence your decision, though, since these kinds of micro-optimization are unlikely to make any difference.

1 不过,这不应影响您的决定,因为这些类型的微优化不太可能产生任何影响。