¿Marcar parámetros como NO anulables en C#/. NET?


¿Hay un atributo simple o contrato de datos que pueda asignar a un parámetro de función que impida que null se pase en C#/. NET? Idealmente, esto también verificaría en tiempo de compilación para asegurarse de que el literal null no se esté utilizando en ningún lugar para él y en tiempo de ejecución throw ArgumentNullException.

Actualmente escribo algo como ...

if (null == arg)
  throw new ArgumentNullException("arg");

... por cada argumento que espero que no sea null.

En la misma nota, hay un opuesto a Nullable<> por lo que lo siguiente sería fail:

NonNullable<string> s = null; // throw some kind of exception
Author: Neil C. Obremski, 2008-11-14

7 answers

Desafortunadamente, no hay nada disponible en tiempo de compilación.

Tengo un poco de solución hacky que he publicado en mi blog recientemente, que utiliza una nueva estructura y conversiones.

En.NET 4.0 con los Contratos de Código , la vida será mucho más agradable. Todavía sería bastante bueno tener sintaxis de lenguaje real y soporte en torno a la no nullabilidad, pero los contratos de código ayudarán mucho.

También tengo un método de extensión en MiscUtil llamado ThrowIfNull lo que lo hace un poco más simple.

Un punto final - ¿alguna razón para usar "if (null == arg)" en lugar de "if (arg == null)"? Encuentro este último más fácil de leer, y el problema que el primero resuelve en C no se aplica a C#.

 63
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-05 15:21:06

Sé que esta es una pregunta MUY antigua, pero esta falta aquí:

Si usa ReSharper, puede usar el Marco anotado .

 12
Author: rsenna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-07 21:48:38

Compruebe los validadores de la biblioteca enterprise. Puedes hacer algo como :

private MyType _someVariable = TenantType.None;
[NotNullValidator(MessageTemplate = "Some Variable can not be empty")]
public MyType SomeVariable {
    get {
        return _someVariable;
    }
    set {
        _someVariable = value;
    }
}

Luego en tu código cuando quieras validarlo:

Microsoft.Practices.EnterpriseLibrary.Validation.Validator myValidator = ValidationFactory.CreateValidator<MyClass>();

ValidationResults vrInfo = InternalValidator.Validate(myObject);
 8
Author: NotMe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-14 21:23:47

Sé que llego increíblemente tarde a esta pregunta, pero siento que la respuesta se volverá relevante a medida que la última iteración importante de C# se acerque a la liberación, y luego se libere. En C # 8.0 se producirá un cambio importante, C # asumirá que todos los tipos no se consideran null.

Según Mads Torgersen:

El problema es que las referencias nulas son muy útiles. En C#, son los valor predeterminado de cada tipo de referencia. ¿Qué más podría el valor predeterminado ¿valor ser? Qué otro valor tendría una variable, hasta que pueda decidir ¿qué más asignarle? ¿Qué otro valor podríamos pavimentar un recién matriz asignada de referencias con, hasta llegar a ¿llenándolo?

También, a veces null es un valor sensible en sí mismo. A veces usted quiere representar el hecho de que, por ejemplo, un campo no tiene un valor. Que está bien pasar "nada" para un parámetro. El énfasis es a veces, sin embargo. Y aquí yace otra parte del problema: Lenguajes como C# no te permiten expresar si un null aquí es un buena idea o no.

Así que la resolución esbozada por Mads, es:

  1. Creemos que es más común querer que una referencia no sea nula. Tipos de referencia nullable sería el tipo más raro (aunque no tenemos buenos datos para decirnos por cuánto), por lo que son los que deberían requerir una nueva anotación.

  2. El lenguaje ya tiene una noción de-y una sintaxis tipos de valor for – nullable. La analogía entre los dos haría que el lenguaje adición conceptualmente más fácil, y lingüísticamente más simple.

  3. Parece correcto que no deba sobrecargarse a usted o a su consumidor con valores nulos engorrosos a menos que haya decidido activamente que los quiero. Nulls, no la ausencia de ellos, debe ser la cosa que usted explícitamente tiene que optar por.

Un ejemplo de la característica deseada:

public class Person
{
     public string Name { get; set; } // Not Null
     public string? Address { get; set; } // May be Null
}

El la vista previa está disponible para Visual Studio 2017, 15.5.4+ vista previa.

 6
Author: Greg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-08 16:50:00

No la más bonita sino:

public static bool ContainsNullParameters(object[] methodParams)
{
     return (from o in methodParams where o == null).Count() > 0;
}

También puedes ser más creativo en el método ContainsNullParameters:

public static bool ContainsNullParameters(Dictionary<string, object> methodParams, out ArgumentNullException containsNullParameters)
       {
            var nullParams = from o in methodParams
                             where o.Value == null
                             select o;

            bool paramsNull = nullParams.Count() > 0;


            if (paramsNull)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var param in nullParams)
                    sb.Append(param.Key + " is null. ");

                containsNullParameters = new ArgumentNullException(sb.ToString());
            }
            else
                containsNullParameters = null;

            return paramsNull;
        }

Por supuesto, podría usar un interceptor o reflexión, pero estos son fáciles de seguir/usar con poca sobrecarga

 0
Author: Jeff Grizzle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-06 11:06:13

Ok esta respuesta es un poco tarde, pero así es como lo estoy resolviendo:

public static string Default(this string x)
{
    return x ?? "";
}

Use este método exension, entonces puede tratar la cadena nula y vacía como la misma cosa.

Por ejemplo

if (model.Day.Default() == "")
{
    //.. Do something to handle no Day ..
}

No es ideal Lo sé ya que hay que recordar llamar por defecto en todas partes, pero es una solución.

 -4
Author: Martin Capodici,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-04 22:09:28
public void foo(int? id, string name)
{
    if (id == null)
    {
       throw new ArgumentNullException("id");
    }
    if (name == null)
    {
       throw new ArgumentNullException("name");
    }

    this.foo = id.Value;
    this.fooName = name;
}

Ahí lo tienes, de lo contrario solo define otra declaración.

 -9
Author: Bas Hermens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-06 11:07:23