2010-02-25 3 views
4

Я пытаюсь получить разницу между методами литья типа.Различные способы преобразования типов. В чем разница

например.

Метод 1

public byte fun() 
{ 
    object value=1; 
    return (byte)value; // this gives me error 
} 

Метод 2

public byte fun() 
{ 
    object value=1; 
    return byte.Parse(value.ToString()); // this runs 
} 

Метод 3

public byte fun() 
{ 
    object value=1; 
    return Convert.ToByte(value); // this runs 
} 

В чем разница между все три. Как они работают внутри страны. Что такое тип значения и тип refrence здесь. Какая функция может преобразовать тип значения реф типа и наоборот

Edit 2

Когда я записывает эту строку, что тип данных «1» будет рассматриваться по умолчанию Int32, байт или что-то другое.

значение объекта = 1;

+0

Кроме того, существует 'bool byte.TryParse (string, out double value)' – AxelEckenberger

+0

@Obalix: должно быть byte.TryPase (string, out byte value) –

ответ

8

Здесь есть много вопросов.

Способ 1 не работает, потому что вы не можете сделать unbox и листинг за одну операцию. Вы устанавливаете «значение» в целое число в штучной упаковке. Когда вы пытаетесь выполнить бросок, вы освобождаете целое число и пытаетесь передать его в байт за одну операцию, что не получается. Это делает работу, кстати:

return (byte)((int)value)); // Unbox, then cast, in two operations 

Метод 2 работает, потому что вы преобразующие целое число в строку, а затем с помощью byte.Parse, чтобы преобразовать его в байт. Это очень дорого, так как он собирается/из строк.

Метод 3 работает, потому что он видит, что объект в значении является IConvertible (int) и использует соответствующую операцию преобразования для преобразования в байт. Вероятно, это более эффективный способ приблизиться к этому, в данном случае. Так как «value» хранит int, а int поддерживает IConvertible, Convert.ToByte будет в основном выполнять нулевую проверку, а затем вызывает Convert.ToByte (int), что довольно быстро (он ограничивает проверку и прямой листинг).

Я бы рекомендовал прочитать запись в блоге Эрика Липперта под названием Representation and Identity. Он подробно описывает литье и объясняет, почему метод 1 терпит неудачу ...

1
// This is a direct cast. It expects that the object 
// in question is already allocated as the data type 
// indicated in the cast 
(byte)value; 

// This is a direct code conversion. It takes the argument 
// and runs through code to create a new variable of the 
// type byte. You'll notice if you include this in different 
// code that value will still be an object but your new 
// data will be a byte type 
byte.Parse(value.ToString()); 

// This will convert any object similarly to the byte.Parse. 
// It is not as fast because it does not have a definitely 
// typed parameter (as parse has string). So it must go 
// through a couple of extra steps to guarantee the conversion 
// is smooth. 
Convert.ToByte(value); 

Прямое литье всегда самое быстрое. Предполагается, что тип уже установлен и распределен, поэтому все, что ему нужно сделать, это переключить его ссылочный тип в памяти. Методы преобразования - это преобразования кода, поэтому они требуют немного больше времени. Я не знаю тестов, но Parse немного быстрее, потому что он имеет дело со специфическим и конкретным байтом (string-> byte). Преобразование является самым медленным из методов преобразования, потому что ему не хватает этой же специфичности.

+0

Его метод один не является прямым приложением, однако ... это приказ unbox +, который потерпит неудачу. –

+0

Кроме того, преобразование выполняется быстрее, так как оно может напрямую использовать int.ToByte (от IConvertible.ToByte). –

+0

@Reed Copsey: Это будет unboxing, если он был первоначально создан как байт. Это не так, это началось как выделение в качестве объекта. Для того, чтобы он был «распакован», он должен сначала быть помещен в бокс от байта к объекту. В этом случае это прямое преобразование, и именно поэтому он терпит неудачу. См. Http://msdn.microsoft.com/en-us/library/b95fkada(VS.80).aspx и http://msdn.microsoft.com/en-us/library/ms173105(VS.80). aspx –

0

Ну вот мой выстрел на него:

Метод 1

Это приведение типа, то есть значение должно быть такого типа, который может быть implcitly или явно конвертируется в байт. Кроме того, значение не должно выходить за пределы байта.

Вызов завершается неудачно, поскольку компилятор не имеет информации о том, какой тип объекта он должен использовать, и, следовательно, не может выполнять неявное или явное преобразование. Ведение

int obj = 1; 
byte b = (byte) obj; 

или

byte b = (byte) (int) obj; 

работы. Второй вариант использует expack unboxing (таким образом, обеспечивая необходимую информацию), как описано в комментарии и публикации Рида Копси. Комментарий link, представленный комментарием Рида Копси, подробно объясняет это.

Для выборок пользовательских объектов использование неявных и явных преобразований - это операторы, которые являются статическими методами, определенными в классе. Для object не существует явных или явных операций (см. link по этой причине), тогда как для int эти операции существуют.

Метод 2

Здесь вы разбор строки значение строки должно быть номером, внутри границы байта. Здесь вы также можете использовать TryParse, который позволяет проверить, будет ли конверсия успешной.

Метод 3

Использует преобразование типа из Convert класса. Это самый гибкий метод, поддерживающий большинство распространенных типов. Здесь значение должно быть конвертировано в число, и значение должно находиться внутри границ байта. Класс Convert использует IConvertible для преобразования между различными типами и, следовательно, является расширяемым.

+1

Неверное описание вашего метода «Метод 1». Это конкретное ограничение на unboxing -ie: unboxing типа T можно только сразу же распаковать в T. См. Http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx –

+0

Не уверен, противоречит ли эта ссылка моему заявлению ...Я предполагаю, что 'int jjj = (int) (short) ooo;' это утверждение, которое вы имеете в виду. Как я его интерпретирую, это эквивалентно «short s = (short) ooo; int i = (int) short; '. И это поведение будет соответствовать тому, что я написал. – AxelEckenberger

+0

Речь не идет о компиляторе, «не имеющем никакой информации о том, какой тип объекта должен быть отличен», а скорее, что тип отличается при распаковке, и вы не можете распаковать + лить в одной операции. –

Смежные вопросы