Вам нужно всего лишь использовать оператора литья, если нет неявный литье, доступное, что компилятор может проверить, является безопасным. Если есть один, и компилятор уверен, что прилив будет успешным, он автоматически сделает это за вас.
Теперь, почему я должен использовать актерский состав? Вы должны использовать бросок, когда вы либо:
- Есть объект типа
A
и вам нужен объект типа B
и есть способ преобразовать A
в B
.
- У вас есть ссылка типа
A
к объекту, и вам необходима ссылка типа B
на тот же объект, и оба A
и B
являются действительными ссылочными типами на этот объект.
Еще один способ думать о нем:
- Когда вы знаете лучше, чем компилятор, и вы знаете, объект является типа компилятор не может.
- Если объект не имеет определенного типа, но вы знаете, что существует допустимое преобразование в этот тип.
И это вызывает способ группировки слепков на основании того, что актеры действительно делает:
- Слепки, которые сохраняют идентичность.
- Каста, которые этого не делают.
1-я группа - это то, что мы называем ссылок на конверсии. Они вообще не меняют объект, они просто меняют тип ссылки, указывающей на объект (очевидно, они применимы только к ссылочным типам, типы значений не могут иметь ссылочные преобразования, потому что вы не можете получить ссылку на значение тип). Обратите внимание, что этот тип трансляции предоставляется самим языком, вы не используете .
Вторая группа - это все преобразования, которые влекут за собой репрезентативное изменение в объекте, то есть биты объекта, возвращаемого приведением, отличаются от битов литого объекта. Эти типы приведений - это операторы implicit
и explicit
, которые можно реализовать в любом классе/структуре C#.
Подробнее об этом можно узнать здесь in this SO answer.
Хорошо, все это очень интересно, но можете ли вы привести конкретные примеры? Да, конечно:
Компилятор знает достаточно:
interface IFoo { }
class Foo: Foo { }
IFoo foo = new Foo();
Существует неявное приведение от Foo
к IFoo
в последнем заявлении: IFoo foo = (Foo)(new Foo());
. Это литье будет успешно всегда, а компилятор знает, есть явный литой (ссылочные преобразования) от Foo
до IFoo
, поэтому он сделает это за вас.
Я знаю лучше, чем компилятор:
object o = "Hello";
var s = (string)o;
Здесь я знаюo
действительно строка и я говорю компилятор: даже если вы думаете o
является объектом, поверьте мне, я знать его строку.
Это также ссылочное преобразование. Строка Hello
никоим образом не тронута, единственное, что мы меняем, это ссылка, указывающая на нее.
Я знаю, что данный объект типа A можно преобразовать в другой объект типа B, хотя никакого ссылочного преобразования не существует.
short s = 1;
int i = s;
Обратите внимание, что short
неint
но случается метод (литая оператор), который знает как преобразовать short
к int
.Здесь у нас есть неявный литой от short
до int
. s
и i
имеют очень разные биты, но кто-то реализовал необходимую логику, которая превращает короткий в int.
Теперь обратите внимание, что это неявный бросок, вам не нужно явно указывать короткую позицию, хотя ничто не мешает вам это делать. Его вполне справедливо: int i = (int)s;
.
double d = 1.5;
int i = (int)d;
Здесь у нас есть тот же тип приведения, но теперь его явный. Если бы вы написали int i = d
, вы получили бы ошибку времени компиляции, потому что приведение не подразумевается.
Это вызывает интересный момент, когда вы, кажется, сражаетесь с приведениями; потеря информации. Хорошей практикой является то, что неявные отливки не теряют информацию, в то время как явное приведение допускается. Это кажется разумным, вы не хотите, чтобы компилятор неявно бросал вещи, теряющие информацию, не сообщая вам; когда вы бросаете short
в int
, нет никакого риска, любой short
вписывается в int
. Это, очевидно, неверно при кастинге от double
до int
, поэтому приведение выполняется как явное. (Замечание о реализовано, это не применяется языком, его дизайнерское решение того, кто написал класс, определяющий операторы литья).
unboxing - это один случай. Нам пришлось делать слишком много кастинга до введения общих методов в C#. Это связано с тем, что слишком многие методы использовали параметр 'object', такой как не общий вариант' List'. Подумайте о событиях, в которых отправитель, если он имеет тип 'object', и вам нужно направить его на« Button », например. Уверен, что оператор 'as' является предпочтительным, но я просто пытаюсь объяснить действительный случай. – user3185569