El compilador de C# arroja un error de argumentos no válidos.¿Por qué?

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

  •  06-07-2019
  •  | 
  •  

Pregunta

Tengo una clase que contiene dos métodos como estos:

public String getFoo(Int32 a)
{
  return getBar(a, "b", null);
}

public String getBar(Int32 a, String b, Int32 c)
{
  //do something
  return "";
}

Sin embargo, cuando compilo mi clase me sale dos errores:

  1. La mejor coincidencia de método sobrecargado para getBar(int,string,int) tiene algunos argumentos no válidos
  2. Argumento '3':no se puede convertir de '<null>' a 'int'

Creo que entiendo por qué recibo este error:El compilador no sabe en el momento de la compilación cuál es el tipo real del objeto.¿Alguien puede confirmar si estoy en lo cierto acerca de la causa del error o señalar el motivo real?

Más importante aún, ¿puedo diseñar mi código de esta manera?Si es así, ¿qué debo hacer para corregir los errores?La razón para diseñar mi clase de esta manera es porque no quiero duplicar el código en getBar, en getFoo.Los dos métodos hacen esencialmente lo mismo excepto que uno toma un tercer parámetro.

Gracias.

¿Fue útil?

Solución

En .NET, existe un concepto distinto entre los tipos de referencia y los tipos de valor.

Un tipo de referencia es un objeto que se asigna en el montón (será una subclase de System.Object). Todo lo que está en la pila es un puntero a este objeto. Debido a eso, es perfectamente válido almacenar un puntero nulo.

Un tipo de valor es un objeto que se asigna en la pila, será una subclase de System.ValueType. Debido a que un tipo de valor vive en la pila, cuando pasa su valor a una función, pasa todo el contenido del objeto.

Los tipos de valor no pueden ser nulos.

La mayoría de los tipos primitivos de C # son tipos de valores. La cadena es un tipo especial de primitivo que en realidad es un tipo de referencia.

En .NET 2.0, MS agregó la capacidad de encerrar un tipo genérico dentro de una estructura para que pueda simular un tipo anulable. Lo que realmente sucede es que la lógica dentro de Nullable & Lt; T & Gt; struct está emulando un nulo para ti.

Lo expresaron usando un atajo de sintaxis agregando un signo de interrogación al tipo, por ejemplo:

int? nullableInt = null;
float? nullableFloat = null;

etc ...

Si no te gusta el int? sintaxis, siempre puede usar Nullable < SomeType >

public String getBar(Int32 a, String b, Nullable<Int32> c)

Como nota al margen, prefiero agregar una sobrecarga al hacer lo que está haciendo, solo para hacer que la sintaxis sea más agradable.

public String getBar(Int32 a, String b)
{
     this.getBar(a,b,null);
}

public String getBar(Int32 a, String b, Nullable<Int32> c)
{
}

Otros consejos

Intente hacer que el tercer argumento para el getBar un int nulable.

Entonces, la firma se vería así:

public String getBar(Int32 a, String b, Int32? c)

Puede obtener más información sobre los tipos anulables en .NET aquí y aquí .

Int32 es un tipo de valor, lo que significa que null no es un argumento válido para parámetros de tipo int?.

Si realmente necesita entradas anulables, use el tipo <=>.

Los dos errores que está viendo son en realidad el mismo error.

Sunny es correcto.
Int32 es un tipo de valor y no puede contener el valor 'nulo'. Si necesita pasar 'nulo' como valor de parámetro, use Nullable en lugar de Int32 como su tipo de argumento.

Puede encontrar más información en Tipos Nullable (C # Guía de programación) en MSDN.

Int32 es un alias para int que es un tipo de valor / no anulable. Para una versión anulable, use System.Nullable o simplemente 'int?'.

Además, no olvide volver a convertir a un int no anulable:

int? nullable = ...;
int non_nullable = nullable??0; 

donde el número indica qué valor debe asumir si es realmente nulo.

Int32 no puede ser nulo. Conviértalo en un tipo anulable:

public String getBar(Int32 a, String b, Int32? c)
{
    if (c.HasValue)
    {
        ...do something with c.Value...
    }
    return "";
}

OK, entonces cinco siete personas propusieron int? como la solución. Propongo otras dos soluciones que podrían ser más apropiadas, dependiendo de la situación;

  • Cree una sobrecarga del método que solo tiene dos argumentos, y omita el null cuando llame:

    public String getFoo(Int32 a)
    {
      return getBar(a, "b", null);
    }
    
    public String getBar(Int32 a, String b)
    {
      //do something else, without the int
    }
    

    Aunque probablemente no desee hacer esto ya que declaró que desea evitar la duplicación de código.

  • Use default en lugar de 0 :

    return getBar(a, "b", default(int));
    

    Por cierto, esto es lo mismo que pasar el valor <=>.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top