Tipi nullable: il modo migliore per verificare la presenza di null o zero in c #

StackOverflow https://stackoverflow.com/questions/633286

  •  08-07-2019
  •  | 
  •  

Domanda

Sto lavorando a un progetto in cui trovo che sto verificando quanto segue in molti, molti posti:

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

più come una curiosità che altro, qual è il modo migliore per verificare entrambi i casi?

Ho aggiunto un metodo di supporto che è:

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

C'è un modo migliore?

È stato utile?

Soluzione

Mi piace if ((item.Rate ?? 0) == 0) { }

Aggiornamento 1:

Puoi anche definire un metodo di estensione come:

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

E usalo in questo modo:

if(item.IsNullOrValue(0)){} // ma non ottieni molto da esso

Altri suggerimenti

Uso dei generici:

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

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

Se T è un tipo di riferimento , value verrà confrontato con null (default(T)), altrimenti, se value type è un default(t), diciamo doppio , false è 0 g, per bool è '\0', per char è <=> e così via ...

Anche se mi piace molto la risposta accettata, penso che, per completezza, anche questa opzione debba essere menzionata:

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

Questa soluzione


&

# 185; Ciò non dovrebbe influenzare la tua decisione, tuttavia, poiché è improbabile che questo tipo di micro-ottimizzazione faccia alcuna differenza.

Questa è davvero solo un'espansione della risposta accettata da Freddy Rios solo usando Generics.

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

NOTA non è necessario controllare il valore predefinito (T) per null poiché abbiamo a che fare con tipi di valore o strutture! Questo significa anche che possiamo tranquillamente presumere che il valore T ToCheck non sarà nullo; Ricordi qui che T? è una scorciatoia Nullable < T > quindi aggiungendo l'estensione a Nullable < T > otteniamo il metodo in int ?, double ?, bool? ecc.

Esempi:

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

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

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

Sono d'accordo con l'utilizzo del ?? operatore.

Se hai a che fare con le stringhe usa if (String.IsNullOrEmpty (myStr))

  

c'è un modo migliore?

Bene, se stai davvero cercando un modo migliore, puoi probabilmente aggiungere un altro livello di astrazione in cima a Rate. Bene, ecco qualcosa che ho appena inventato usando 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) { }
    }
}

Il tuo esempio di codice fallirà. Se obj è nullo, obj.ToString () si tradurrà in un'eccezione di riferimento null. Avrei abbreviato il processo e verificato la presenza di un oggetto null all'inizio della funzione di supporto. Per quanto riguarda la tua vera domanda, qual è il tipo che stai verificando per null o zero? Su String c'è una grande funzione IsNullOrEmpty, mi sembra che questo sarebbe un grande uso dei metodi di estensione per implementare un metodo IsNullOrZero sull'int? tipo.

Modifica: ricorda, il '?' è solo zucchero del compilatore per il tipo INullable, quindi probabilmente potresti prendere un INullable come parm e poi confrontarlo con null (parm == null) e se non null confrontare con zero.

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

Non dimenticare, per le stringhe, puoi sempre usare:

String.IsNullOrEmpty(str)

Invece di:

str==null || str==""

Un passo avanti rispetto a il simpatico risposta . Ora, impedendo 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));
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top