Pergunta

Eu definida a seguinte estrutura:

public struct Call
{
    public SourceFile caller;
    public SourceFile callee;

    public Call(SourceFile caller, SourceFile callee)
    {
        this.caller = caller;
        this.callee = callee;
    }
}

Mais tarde, eu atribuir a ele a Marca de propriedade de outro objeto:

line.Tag = new Call(sf1, sf2);

Mas quando eu tento recuperar a propriedade Tag como assim,

Call call = line.Tag as Call;

O Visual Studio dá o seguinte erro de tempo de compilação:

O operador deve ser utilizado dentro de um tipo de referência ou tipo anulável

Qual é o significado disso?E como eu posso resolver isso?

Foi útil?

Solução

Uma estrutura é um tipo de valor, portanto não pode ser usado com o as operador. o as O operador deve ser capaz de atribuir um valor de nulo se o elenco falhar. Isso só é possível com um tipo de referência ou um tipo de valor anulado.

Existem algumas maneiras de resolver isso, mas sua melhor aposta é mudar seu Call digite de uma estrutura para uma classe. Isso mudará essencialmente o seu tipo de um tipo de valor para um tipo de referência, que permite o as Operador para atribuir um valor de nulo se o elenco falhar.

Para mais informações sobre tipos de valor versus tipos de referência, isto é um artigo decente. Além disso, dê uma olhada no MSDN:

Outras dicas

Algumas das respostas existentes não são bastante certo. Você não pode usar não nulo tipos com as, porque o resultado de as é o valor nulo do tipo se o primeiro operando não for realmente do tipo apropriado.

No entanto, você posso usar as com tipos de valor ... se eles são anuláveis:

int a = 10;
object o = a;

int? x = o as int?; // x is a Nullable<int> with value 10
long? y = o as long?; // y is a Nullable<long> with the null value

Então você poderia usar:

Call? call = line.Tag as Call?;

Então você pode usá -lo como:

if (call != null)
{
    // Do stuff with call.Value
}

Duas advertências embora:

  • Na minha experiência, isso é mais lento do que apenas usar is seguido de um elenco
  • Você deve reconsiderar seriamente seu atual Call modelo:
    • Está expondo campos públicos, que geralmente é fraco encapsulamento
    • É um tipo de valor mutável, que é quase certamente um erro

Eu sugiro fortemente que você faça uma aula - em que ponto esse problema desaparece de qualquer maneira.

Outro pensamento: se a tag deve sempre ser um Call, então é melhor lançá -lo:

Call call = (Call) line.Tag;

Dessa forma, se os dados não correspondem à sua expectativa (ou seja, há algum bug, de modo que o Tag não é um Call) Então você descobre isso mais cedo, e não depois de fazer algum outro trabalho. Observe que este elenco se comportará de maneira diferente, dependendo se Call é uma estrutura ou uma classe, se Tag é nulo - você pode lançar um valor nulo em uma variável de um tipo de referência (ou um tipo de valor anulado), mas não para um tipo de valor não indicado.

A partir do C# Spec

§7.10.11 O operador é usado para converter explicitamente um valor para um determinado tipo de referência ou tipo anulável.Ao contrário de um elenco de expressão (§7.7.6), o operador como nunca lança uma excepção.Em vez disso, se o indicado a conversão não é possível, o valor resultante é null.

Referências e tipos anuláveis podem ser null.Stucts são tipos de valor, de modo que eles não podem ser nulos.

Call? call = line.Tag as Call?;

É uma limitação de C#. Se o tipo fosse um tipo de referência, se o elenco falhar, ele simplesmente retornaria 'nulo', mas como é um tipo de valor, não sabe o que retornar quando o elenco falhar.

Você deve substituir o uso de dois: 'é' e 'como'

if (line.Tag is Call) {
  call = (Call)line.Tag;
} else {
  // Do whatever you would do if as returned null.
}

Qual é o significado - como indicado, as estruturas são tipos de valor.

Como posso resolvê -lo - mude para

Call call = line.Tag;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top