Pergunta

Aprendizagem C # livro de De Jesse Liberty, ele diz: "Objetos de um tipo pode ser convertido em objetos de outro tipo. Isso é chamado de fundição."

Se você investigar o IL gerado a partir do código abaixo, você pode ver claramente que a atribuição fundido não está fazendo a mesma coisa que a atribuição convertido. No primeiro caso, você pode ver o boxe / unboxing ocorrendo; No último você pode ver uma chamada para um método de conversão.

Eu sei que no final pode ser apenas uma diferença semântica bobo - mas está lançando apenas uma outra palavra para a conversão. Eu não quero ser sarcástico, mas eu não estou interessado em intuição de ninguém sobre isso - opiniões não contam aqui! Pode apontar alguém para uma referência definitiva que confirma ou nega se fundição e convertendo são a mesma coisa?

    object x;
    int y;

    x = 4;

    y = ( int )x;

    y = Convert.ToInt32( x );

Obrigado

rp

Nota adicionado depois do comentário de Matt sobre explícito / implícito:

Eu não acho implícita / explícita é a diferença. No código eu postei, a mudança é explícita em ambos os casos. Uma conversão implícita é o que ocorre quando você atribui um curto para um int.

Nota para Sklivvz:

Eu queria a confirmação de que a minha suspeita da frouxidão da Jesse Liberdade de idioma (caso contrário, normalmente lúcida e clara) foi correta. Pensei que Jesse Liberty estava sendo um pouco frouxa com sua linguagem. Eu entendo que elenco é encaminhado na hierarquia de objetos -. Ou seja, você não pode converter de um inteiro para uma string, mas você poderia lançar a partir de exceção personalizada derivado de System.Exception a um System.Exception.

É interessante, porém, que quando você tentar lançar a partir de um int para uma string o compilador diz-lhe que ele não poderia "converter" o valor. Talvez Jesse é mais correto do que eu pensava!

Foi útil?

Solução

A resposta é simples:. Isso depende

Para tipos de valores, fundição irá envolver genuinamente convertê-lo para um tipo diferente. Por exemplo:

float f = 1.5f;
int i = (int) f; // Conversion

Quando os unboxes fundição expressão, o resultado (supondo que ele funciona) é normalmente apenas uma cópia do que estava na caixa, com o mesmo tipo. Há exceções, no entanto - você pode unbox de um int em caixa para um ENUM (com um tipo subjacente de int) e vice-versa; Da mesma forma você pode unbox de um box int a um Nullable .

Quando a expressão de fundição é de um tipo de referência para outro e nenhuma conversão definida pelo usuário está envolvido, não há nenhuma conversão, tanto quanto o próprio objeto está em causa - apenas o tipo de referência "mudanças "- e isso é realmente apenas a maneira que o valor é considerado, em vez da própria referência (que serão os mesmos bits como antes). Por exemplo:

object o = "hello";
string x = (string) o; // No data is "converted"; x and o refer to the same object

Quando conversões definidas pelo usuário se envolver, este normalmente implica que retornam um objeto / valor diferente. Por exemplo, você poderia definir uma conversão para string para o seu próprio tipo - e este certamente não seriam os mesmos dados que o seu próprio objeto. (Pode ser uma seqüência existente referido de seu objeto já, é claro.) Na minha experiência, geralmente existem conversões definidas pelo usuário entre tipos de valor, em vez de tipos de referência, de modo que este raramente é um problema.

Todos estes contam como conversões em termos de especificação - mas nem todos eles contam como converter um objeto em um objeto de um tipo diferente. Eu suspeito que este é um caso de Jesse Liberty sendo solto com a terminologia -. Tenho notado que na programação C # 3.0, que eu fui apenas leitura

Será que a cobertura de tudo?

Outras dicas

Absolutamente não!

Convert tenta levá-lo um Int32 através de "todos os meios possíveis". Elenco faz nada do tipo. Com elenco você está dizendo ao compilador para tratar o objeto como Int, sem conversão.

Você deve sempre usar elenco quando você sabe (pelo design) que o objeto é um Int32 ou outra classe que tem um operador de conversão para Int32 (como float, por exemplo).

Converter deve ser usado com String, ou com outras classes.

Tente este

static void Main(string[] args)
{
    long l = long.MaxValue;

    Console.WriteLine(l);

    byte b = (byte) l;

    Console.WriteLine(b);

    b = Convert.ToByte(l);

    Console.WriteLine(b);

}

Resultado:

9223372036854775807

255

Exceção não tratada:

System.OverflowException: Valor é maior do que Byte.MaxValue ou menos que Byte.MinValue em System.Convert.ToByte (valor Int64) [0x00000] em Test.Main (System.String [] args) [0x00019] em /home/marco/develop/test/Exceptions.cs:15

A melhor explicação que eu vi pode ser visto abaixo, seguido de um link para a fonte:

" ... A verdade é um pouco mais complexa do que isso. NET fornece três métodos de ir do ponto A ao ponto B, por assim dizer.

Em primeiro lugar, há a conversão implícita. Este é o elenco que não faz exigem que você faça algo mais do que uma atribuição:

int i = 5;
double d = i;

Estes são também chamados "alargamento conversões" e .NET permite que você executá-las sem qualquer operador de conversão, porque você nunca pode perder qualquer informações fazê-lo: a possível intervalo de valores válidos de um duplo engloba o intervalo de valores válidos para um int e, em seguida, alguns, assim você nunca vai fazer esta tarefa e, em seguida, descobrir a sua horror que o tempo de execução cair alguns dígitos fora de seu valor int. Para tipos de referência, a regra atrás de uma conversão implícita é que o elenco nunca poderia jogar um InvalidCastException: é claro para o compilador que o elenco é sempre válido.

Você pode fazer novos operadores implícita elenco para seus próprios tipos (que meios que você pode fazer moldes implícitas que quebram todas as regras, se você é estúpido sobre isso). A regra básica é que um implícito elenco nunca pode incluir a possibilidade de perda de informações no transição.

Note que a representação subjacente fez mudança neste conversão:. um duplo é representado de forma completamente diferente de um int

O segundo tipo de conversão é uma conversão explícita. Uma conversão explícita é requerido onde quer que haja a possibilidade de perda de informações, ou existe a possibilidade de que o elenco pode não ser válida e, portanto, lançar um InvalidCastException:

double d = 1.5;
int i = (int)d;

Aqui você está, obviamente, vai informações perder: i será de 1 após a elenco, então a 0,5 se perde. Isso também é conhecido como um "estreitamento" conversão, e o compilador requer que você incluir uma conversão explícita (Int) para indicar que sim, você sabe que a informação pode ser perdida, mas você não se importa.

Da mesma forma, com tipos de referência o compilador requer conversões explícitas em situações em que o elenco pode não ser válido em tempo de execução, como um sinal que sim, você sabe que há um risco, mas você sabe o que está fazendo.

O terceiro tipo de conversão é aquele que envolve tal uma mudança radical na representação que os designers não forneceu até mesmo uma explícita elenco: eles fazem você chamar um método, a fim de fazer a conversão:

string s = "15";
int i = Convert.ToInt32(s);

Note que não há nada que absolutamente requer uma chamada de método aqui. casts implícitas e explícitas são chamadas de método também (é assim que você faz seu próprio). Os designers poderia facilmente ter criado uma explícita operador de conversão que converteu uma string para um int. A exigência de que você chamar um método é uma escolha estilística, em vez de um direito fundamental exigência da língua.

O raciocínio estilística é algo como isto: String-a-int é um conversão complicado com muitas oportunidades para as coisas horrivelmente errado:

string s = "The quick brown fox";
int i = Convert.ToInt32(s);

Como tal, a chamada de método dá-lhe a documentação de ler, e uma ampla sugerir que isso é algo mais do que apenas um elenco rápida.

Ao projetar seus próprios tipos (particularmente seus próprios tipos de valor), você pode decidir criar operadores de conversão e funções de conversão. As linhas dividindo "conversão implícita", "conversão explícita" e "função de conversão" território são um pouco embaçada, para que as pessoas diferentes podem fazer diferente decisões quanto ao que deve ser o que. Apenas tente manter em mente perda de informações, e potencial para exceções e dados inválidos, e que deve ajudá-lo a decidir. "

  • Bruce Wood, 16 de novembro de 2005

http://bytes.com/forum/post1068532-4.html

Fundição envolve referências

List<int> myList = new List<int>();
//up-cast
IEnumerable<int> myEnumerable = (IEnumerable<int>) myList;
//down-cast
List<int> myOtherList = (List<int>) myEnumerable;

Repare que as operações contra myList, tais como a adição de um elemento, são reflectidas em myEnumerable e myOtherList. Isso é porque eles são todas as referências (de vários tipos) para a mesma instância.

Up-casting é seguro. Baixo-casting pode gerar erros de tempo de execução se o programador cometeu um erro no tipo. Seguro para baixo-casting está além do escopo desta resposta.

A conversão envolve instâncias

List<int> myList = new List<int>();
int[] myArray = myList.ToArray();

myList é usado para produzir myArray. Esta é uma conversão não-destrutivo (myList funciona perfeitamente bem após esta operação). Note também que as operações contra myList, tais como a adição de um elemento, não são reflectidas em meuArray. Isso é porque eles são instâncias completamente separadas.

decimal w = 1.1m;
int x = (int)w;

Existem operações usando a sintaxe elenco em C # que são realmente conversões .

Semântica à parte, um rápido teste revela que eles são Não equivalente!
Eles fazem a tarefa de forma diferente (ou talvez, eles fazem tarefas diferentes).

x=-2.5 (int)x=-2 Convert.ToInt32(x)=-2
x=-1.5 (int)x=-1 Convert.ToInt32(x)=-2
x=-0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 1.5 (int)x= 1 Convert.ToInt32(x)= 2
x= 2.5 (int)x= 2 Convert.ToInt32(x)= 2

Observe os casos x=-1.5 e x=1.5.

Um elenco está dizendo o compilador / interperter que o objeto na verdade é desse tipo (ou tem uma BaseType / Interface desse tipo). É uma coisa muito rápido para fazer comparação com um convertido, onde ele não é mais o compilador / interperter fazendo o trabalho, mas uma função actualling analisar uma corda e fazer matemática para converter para um número.

Fundição sempre significa mudar o tipo de dados de um objeto. Isto pode ser feito, por exemplo, através da conversão de um valor flutuador para um valor inteiro, ou por reinterpreting os bits. É usally um (leia-se:-compilador suportado) apoiou-language. Operação

O termo "conversão" é por vezes utilizado para a fundição, mas geralmente é feito por alguma biblioteca ou o seu próprio código e não resulta necessariamente na mesma como fundição. Por exemplo, se você tiver um valor de peso imperial e convertê-lo em peso métrica, pode permanecer o mesmo tipo de dados (digamos, float), mas tornam-se um número diferente. Outro exemplo típico é a conversão de graus para radiano.

De maneira language- / framework agnóstica de falar, a conversão de um tipo ou classe para outra é conhecido como carcaça . Isto é verdade para .NET, bem como, suas primeiras quatro linhas mostram:

object x;
int y;

x = 4;

y = ( int )x;

C e C-como línguas (como C #) usar a sintaxe (newtype)somevar para a fundição. Em VB.NET, por exemplo, existem explícita funções internas para isso. A última linha seria escrito como:

y = CInt(x)

Ou, para os tipos mais complexos:

y = CType(x, newtype)

Onde 'C', obviamente, é a abreviação de 'cast'.

.NET também tem a função Convert(), no entanto. Este não é um built-in recurso de linguagem (ao contrário do acima de dois), mas sim de quadro. Isto torna-se mais clara quando você usa uma linguagem que não é necessariamente usado em conjunto com NET: eles ainda muito provável têm seus próprios meios de casting, mas do .NET que acrescenta Convert()

.

Como Matt diz, a diferença no comportamento é que Convert() é mais explícito. Ao invés de simplesmente dizer ao compilador para y deleite como um equivalente inteiro de x, você está dizendo isso especificamente para x alter de tal forma que é adequado para a classe inteira, então atribuir o resultado para y.

No seu caso particular, o elenco faz o que é chamado de 'unboxing', enquanto Convert() vai realmente começar o valor inteiro. O resultado aparecerá o mesmo, mas há diferenças sutis melhor explicadas por Keith .

De acordo com a Tabela 1-7 intitulado "Métodos para conversão explícita" na página 55 no Capítulo 1, Lição 4 de MCTS Self-Paced Training Kit (exame 70-536): Microsoft® .NET Framework 2.0 Aplicação Fundação para o desenvolvimento , há certamente uma diferença entre eles.

System.Convert é independente de linguagem e convertidos "entre os tipos que implementam a System.IConvertible de interface ."

(tipo) operador de conversão é um C # espec�ico recurso de linguagem que converte "entre os tipos que definem operadores de conversão ."

Além disso, ao implementar conversões personalizadas, difere conselhos entre eles.

Por seção intitulada Como implementar Conversão em Tipos personalizados em pp. 56-57 na lição já referido, operadores de conversão (fundição) são destinadas a simplificar as conversões entre tipos numéricos, enquanto Convert () permite conversões específicas da cultura .

Qual a técnica que você escolher depende do tipo de conversão que você deseja executar:

  • definir operadores conversão para simplificar estreitamento e alargamento conversões entre tipos numéricos.

  • Implementar System.IConvertible para permitir a conversão através System.Convert. Use esta técnica para permitir conversões específicas da cultura.

  • ...

Deve ser mais claro agora que, desde o operador de conversão elenco é implementado separadamente a partir da interface IConvertible, que Convert () não é necessariamente apenas um outro nome para a fundição. (Mas eu posso imaginar que uma implementação pode se referir a outro para garantir a consistência).

Não se esqueça dos outros métodos de fundição e convertendo variáveis: como, analisar TryParse bem como a conversão implícita entre tipos de dados compatíveis.

Este site tem uma boa amostra do que as saídas para a maioria dos métodos: C # Boxing e Unboxing

Assim, dado estas variáveis ??de amostra:

int i = 3, x;
long l;
string s = "5";

Basicamente, você pode ter a conversão implícita, entre dois tipos compatíveis:

l = i;

conversão explícita usando unboxing ou o como palavra-chave:

s = (string)i;
//or
s = i as string;

Conversões explícitas usando métodos de System.Convert:

i = System.Convert.ToInt32(s);

conversões explícito usando métodos de um tipo de dados definidos:

i = int.Parse(s);
i = int.TryParse(s, x);

conversões explícito usando métodos a partir de um exemplo de uma variável:

s = i.ToString();

Eu acho que carcaça é simplesmente uma maneira de fazer atribuições entre dois tipos compatíveis.

Convertendo é se você precisa copiar explicitamente um valor de um tipo incompatível para outro, e você não pode confiar mal coerção .

Algumas informações bom também no MSDN: Fundição e Tipo Conversões

Fundição é, essencialmente, apenas dizendo o tempo de execução para "fingir" o objeto é o novo tipo. Na verdade, não converter ou alterar o objeto de qualquer forma.

Convert, no entanto, irá realizar operações de transformar um tipo para outro.

Como um exemplo:

char caster = '5';
Console.WriteLine((int)caster);

A saída dessas declarações serão 53, porque todo o tempo de execução fez é olhar para o padrão de bits e tratá-lo como um int. O que você acabar ficando é o valor ASCII do caractere 5, em vez do número 5.

Se você usar Convert.ToInt32 (rodízio) no entanto, você terá 5 porque ele realmente lê a corda e modifica-lo corretamente. (Essencialmente ele sabe que o valor ASCII 53 é realmente o valor inteiro 5).

A diferença não é se a conversão é implícita ou explícita. O primeiro se existe um elenco, o segundo é uma chamada mais explícito para uma função que converte. Eles provavelmente vai fazer sobre a mesma coisa de maneiras diferentes.

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