Tipos que aceptan valores null:la mejor manera de comprobar si el valor es nulo o cero en c#

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

  •  08-07-2019
  •  | 
  •  

Pregunta

Estoy trabajando en un proyecto donde me encuentre estoy buscando el siguiente en muchos, muchos lugares:

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

más como curiosidad que otra cosa, ¿cuál es la mejor manera de comprobar para ambos casos?

He añadido un método auxiliar que es:

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

Hay una manera mejor?

¿Fue útil?

Solución

Me gusta if ((item.Rate ?? 0) == 0) { }

Actualización 1:

También podría definir un método de extensión como:

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

Y úsalo así:

if(item.IsNullOrValue(0)){} // pero no obtienes mucho de eso

Otros consejos

El uso de medicamentos genéricos:

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

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

Si T es un tipo de referencia, value será comparado con null ( default(T) ), de lo contrario, si T es un value type, digamos doble, default(t) es 0d, por bool es false, para char es '\0' y así sucesivamente...

Aunque me gusta bastante la respuesta aceptada, creo que, para completar, esta opción también debería mencionarse:

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

Esta solución


& # 185; Sin embargo, esto no debería influir en su decisión, ya que es poco probable que este tipo de micro-optimización haga alguna diferencia.

Esto es realmente solo una expansión de la respuesta aceptada de 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 ¡no necesitamos verificar que el valor predeterminado (T) sea nulo ya que estamos tratando con tipos de valores o estructuras! Esto también significa que podemos asumir con seguridad que T valueToCheck no será nulo; ¿Recuerdas aquí que T? es taquigrafía Nullable < T > entonces agregando la extensión a Nullable < T > obtenemos el método en int ?, double ?, bool? etc.

Ejemplos :

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

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

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

Estoy de acuerdo con usar el ?? operador.

Si está tratando con cadenas, use if (String.IsNullOrEmpty (myStr))

  

¿hay una mejor manera?

Bueno, si realmente está buscando una mejor manera, probablemente pueda agregar otra capa de abstracción sobre Rate. Bueno, aquí hay algo que acabo de inventar 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) { }
    }
}

Tu muestra de código fallará. Si obj es nulo, obj.ToString () dará como resultado una excepción de referencia nula. Cortaría el proceso y buscaría un obj nulo al comienzo de su función auxiliar. En cuanto a su pregunta real, ¿cuál es el tipo que está buscando nulo o cero? En String hay una gran función IsNullOrEmpty, me parece que este sería un gran uso de los métodos de extensión para implementar un método IsNullOrZero en el int? tipo.

Editar: Recuerde, el '?' es solo el compilador de azúcar para el tipo INullable, por lo que probablemente podría tomar un INullable como parm y luego compararlo con nulo (parm == nulo) y, si no, nulo, comparar con cero.

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

No lo olvide, para cadenas, siempre puede usar:

String.IsNullOrEmpty(str)

En lugar de:

str==null || str==""

Un paso más allá de Joshua Shannon es agradable respuesta . Ahora con la prevención de 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));
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top