Pergunta

Há algo de errado em usar um operador implícito como o seguinte:

//linqpad c# program example
void Main()
{
    var testObject = new MyClass<int>() { Value = 1 };

    var add = 10 + testObject; //implicit conversion to int here
    add.Dump(); // 11
}

class MyClass<T>
{
    public T Value { get; set; }
    public static implicit operator T (MyClass<T> myClassToConvert)
    {
        return myClassToConvert.Value;
    }
}

Eu estava pensando que poderia tratar como exemplo do objeto como um tipo de valor dessa maneira, mas, como nunca vi um exemplo disso, pensei que talvez houvesse uma razão não fazer algo assim que alguém poderia apontar?

No meu código real, eu estava pensando em fazer isso como parte de uma camada de abstração de dados, para que eu pudesse devolver objetos com informações que descrevem os dados subjacentes, mas permitir que o código lógico o trate como um tipo de valor quando tudo o que precisa saber sobre é o valor e, ao mesmo tempo, mantenha tudo agradável e digno seguro com os genéricos.

Foi útil?

Solução

Se todos os seguintes são verdadeiros:

  • tudo possíveis valores do seu MyClass<T> tipo (incluindo null Se não for um tipo de valor!) Mapear para um valor válido de T

  • o operador implícito nunca joga (nem mesmo para null!)

  • A conversão implícita faz sentido semântico e não é confuso para o programador do cliente

Então não há nada de errado com isso. Claro que você poderia Faça qualquer uma dessas três coisas, mas seria um design ruim. Em particular, um operador implícito que os arremessos pode ser muito difícil de depurar, porque o local onde é chamado não diz que está sendo chamado.

Por exemplo, considere que T? não tem conversão implícita para T (Onde T é, é claro, um tipo de valor). Se houvesse um operador tão implícito, teria que jogar quando o T? é nulo, pois não há valor óbvio para converter null para isso faria sentido para algum Tipo de valor T.


Deixe -me dar um exemplo em que tive problemas para depurar um problema em que o operador implícito jogou:

public string Foo()
{
    return some_condition ? GetSomething() : null;
}

Aqui, GetSomething devolveu algo do tipo que escrevi que tem uma conversão implícita definida pelo usuário para string. Eu fiz certeza absoluta este GetSomething nunca poderia voltar null, e ainda assim eu tenho um NullReferenceException! Por quê? Porque o código acima é não equivalente a

return some_condition ? (string)GetSomething() : (string)null;

mas para

return (string)(some_condition ? GetSomething() : (Something)null);

Agora você pode ver onde o null veio de!

Outras dicas

Esse é um ótimo padrão. Lembre -se de que para usá -lo como uma variável de tipo T, você tem que lançá -lo explicitamente para T, ou atribui -lo a uma variável de tipo T. O elenco ocorrerá automaticamente em chamadas de método e outras coisas (como o seu exemplo de adição) que tomam um T.

Conversão implícita sem atribuição?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top