web-dev-qa-db-ja.com

Nullable型:C#でNullまたはゼロをチェックする最良の方法

私は多くの多くの場所で次のことを確認しているプロジェクトに取り組んでいます:

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);
}

もっと良い方法はありますか?

71
nailitdown

if ((item.Rate ?? 0) == 0) { }が好き

更新1:

次のような拡張メソッドを定義することもできます。

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

そして、次のように使用します:

if(item.IsNullOrValue(0)){} //しかし、そこから多くを得ることはありません

139
eglasius

ジェネリックの使用:

_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の場合参照型valuenulldefault(T))と比較され、そうでない場合はTは_value type_です。たとえば、double、default(t)は0d、boolはfalse、charは_'\0'_などです...

41
CMS

私は受け入れられた答えがとても好きですが、完全を期すために、このオプションも同様に言及されるべきだと思います:

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

このソリューション


¹これらの種類のマイクロ最適化によって違いが生じる可能性は低いため、これは決定に影響を与えません。

27
Heinzi

これは、ジェネリックのみを使用したフレディリオスの受け入れられた回答の単なる拡張です。

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));
}

[〜#〜] note [〜#〜]値型または構造体のいずれかを扱っているため、default(T)のnullをチェックする必要はありません!これは、T valueToCheckがnullでないと安全に想定できることも意味します。ここでTを覚えていますか? Nullable <T>の省略形であるため、Nullable <T>に拡張子を追加することで、int?、double?、bool?のメソッドを取得できます。等.

例:

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

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

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

より良い方法はありますか?

まあ、本当にもっと良い方法を探しているなら、おそらく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(アイテム内の可変アイテム)
 Console.WriteLine( "アイテム価格:{0: C} "、item.GetPrice()); 
} 
} 
 
 public abstract class ItemBase 
 {
 public abstractレートレート{取得; } 
 public int GetPrice()
 {
 // Rate == 0またはRate == null 
 return 1 * Rateを確認する必要はありません。値; 
} 
} 
 
 public class Item:ItemBase 
 {
 private readonly Rate _Rate; 
 public override Rate Rate {get {return _Rate; }} 
 public Item(Rate rate){_Rate = rate; } 
} 
 
シールドクラス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;セットする; } 
 public virtual bool HasValue {get {return(Value> 0); }} 
 public Rate(int value){値=値; } 
} 
 
 public class NullRate:Rate 
 {
 public override bool HasValue {get {return false; }} 
 public NullRate():base(0){} 
} 
} 
2
Sung M. Kim

??の使用に同意しますオペレーター。

文字列を扱う場合は、if(String.IsNullOrEmpty(myStr))を使用します

2
Nick Josevski

コードサンプルは失敗します。 objがnullの場合、obj.ToString()はnull参照例外になります。プロセスを短縮して、ヘルパー関数の開始時にnull objをチェックします。あなたの実際の質問に関して、あなたがnullまたはゼロをチェックしているタイプは何ですか? Stringには素晴らしいIsNullOrEmpty関数がありますが、これはintにIsNullOrZeroメソッドを実装するための拡張メソッドの素晴らしい使用でしょうか?タイプ。

編集:覚えて、「?」 INullable型のコンパイラシュガーであるため、おそらくINullableをparmとして使用し、jsutでnullと比較し(parm == null)、nullでない場合はゼロと比較できます。

2
Walden Leverich

忘れないでください、文字列にはいつでも使用できます:

String.IsNullOrEmpty(str)

の代わりに:

str==null || str==""
0
Chris
public static bool nz(object obj)
{
    return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}
0
Shea
class Item{  
 bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}
0
dtroy

ジョシュアシャノン のニース 回答 からさらに一歩。 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));
    }
}
0
Deilan