C # compilador gera erro argumentos inválidos. Por quê?
Pergunta
Eu tenho uma classe que contém dois métodos como estes:
public String getFoo(Int32 a)
{
return getBar(a, "b", null);
}
public String getBar(Int32 a, String b, Int32 c)
{
//do something
return "";
}
No entanto, quando eu compilar minha classe eu recebo dois erros:
- O melhor correspondência método sobrecarregado para GetBar (int, string, int) tem alguns argumentos inválidos
- O argumento '3': não podem converter de '
<null>
' para 'int'
Eu acho que entendo por que estou recebendo este erro: o compilador não sabe no momento da compilação que o tipo real do objeto. Alguém pode confirmar se estou correto sobre a causa do erro ou ponto o motivo real?
Mais importante, eu posso projetar meu código dessa maneira? Se assim for, o que eu preciso fazer para corrigir os erros? Minha razão para projetar minha classe desta forma é porque eu não quero duplicar o código no GetBar, em getFoo. Os dois métodos de fazer essencialmente a mesma coisa, exceto um tem um terceiro parâmetro.
Graças.
Solução
NET, existe um conceito distinto entre tipos de referência e tipos de valor.
Um tipo de referência é um objecto que é atribuído na pilha (Vai ser uma subclasse de System.Object). Tudo o que está na pilha é um ponteiro para este objeto. Por isso, é perfeitamente válida para armazenar um ponteiro nulo.
Um tipo de valor é um objeto que é alocado na pilha, ele vai ser uma subclasse de System.ValueType. Porque um tipo de valor vive na pilha, quando você passa o seu valor para uma função, você passa todo o conteúdo do objeto.
Tipos de valor não pode ser nulo.
A maioria C # tipos primitivos são tipos de valor. String é um tipo especial de primitivo que é na verdade um tipo de referência.
.NET 2.0, MS adicionado a capacidade para incluir um tipo genérico dentro de uma estrutura de modo que ele pode simular um tipo nulo. O que realmente acontece é que o interior lógica do Nullable
Eles expressaram-lo usando um atalho sintaxe, adicionando um ponto de interrogação para o tipo, por exemplo:
int? nullableInt = null;
float? nullableFloat = null;
etc ...
Se você não gosta do int? sintaxe, você sempre pode usar Nullable
public String getBar(Int32 a, String b, Nullable<Int32> c)
Como uma nota lateral, eu prefiro adicionar uma sobrecarga ao fazer o que está fazendo, apenas para tornar o mais agradável sintaxe.
public String getBar(Int32 a, String b)
{
this.getBar(a,b,null);
}
public String getBar(Int32 a, String b, Nullable<Int32> c)
{
}
Outras dicas
Int32
é um tipo de valor, o que significa null
não é um argumento válido para parâmetros do tipo Int32
.
Se você realmente precisa ints anuláveis, use o tipo int?
.
Os dois erros que você está vendo são realmente o mesmo erro.
Sunny está correto.
Int32 é um tipo de valor e não pode conter o valor 'null'. Se você precisa passar 'nulo' como um valor de parâmetro, use Nullable vez de Int32 como o tipo de argumento.
Você pode encontrar mais informações em tipos anuláveis ??(C # Guia de programação) no MSDN.
Int32 é um alias para int que é um valor de tipo / não-nulo. Para uma versão anulável dele usar System.Nullable ou simplesmente 'int?'.
Também não se esqueça de converter de volta para um int não nulo:
int? nullable = ...;
int non_nullable = nullable??0;
onde o número indica qual o valor que deve assumir se ele é de fato nula.
Int32 não pode ser nulo. Torná-lo um tipo anulável em vez disso:
public String getBar(Int32 a, String b, Int32? c)
{
if (c.HasValue)
{
...do something with c.Value...
}
return "";
}
OK, então cinco sete pessoas proposto int?
como a solução. Proponho duas outras soluções que pode ser mais apropriado, dependendo da situação;
-
Criar uma sobrecarga do método que só tem dois argumentos, e omitir o
null
ao chamar:public String getFoo(Int32 a) { return getBar(a, "b", null); } public String getBar(Int32 a, String b) { //do something else, without the int }
Embora você provavelmente não quer fazer isso desde que você disse que você queria evitar a duplicação de código.
-
Use
default
vez denull
:return getBar(a, "b", default(int));
A propósito, este é o mesmo que passar o valor
0
.