2017-01-22 2 views
1

Я немного смущен тем, что именно представляет собой объект, и что он используется. Я прочитал документацию MSDN о Casting and type conversion, где я вижу, что для явного преобразования вам нужно использовать оператор трансляции. Я понимаю пример, приведенный в документации, что вам нужно использовать оператор трансляции, если вы можете потерять некоторые данные при преобразовании одного типа в другой.Что такое литье объектов?

Я просто смущен тем, как вы бросаете объекты? Я предполагаю, что объекты - это экземпляры класса, которые могут содержать больше информации, чем просто простой тип данных? Итак, как, почему и когда вам нужно было бросить объект?

Я видел пример заливки объекта, который просто:

SomeType name = (SomeType)obj; 

Могу ли я что-то отсутствует, или это отливка объект? Если это так, в каких сценариях вам понадобится создать такой объект?

+0

unboxing - это один случай. Нам пришлось делать слишком много кастинга до введения общих методов в C#. Это связано с тем, что слишком многие методы использовали параметр 'object', такой как не общий вариант' List'. Подумайте о событиях, в которых отправитель, если он имеет тип 'object', и вам нужно направить его на« Button », например. Уверен, что оператор 'as' является предпочтительным, но я просто пытаюсь объяснить действительный случай. – user3185569

ответ

2

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

Теперь, почему я должен использовать актерский состав? Вы должны использовать бросок, когда вы либо:

  • Есть объект типа A и вам нужен объект типа B и есть способ преобразовать A в B.
  • У вас есть ссылка типа A к объекту, и вам необходима ссылка типа B на тот же объект, и оба A и B являются действительными ссылочными типами на этот объект.

Еще один способ думать о нем:

  • Когда вы знаете лучше, чем компилятор, и вы знаете, объект является типа компилятор не может.
  • Если объект не имеет определенного типа, но вы знаете, что существует допустимое преобразование в этот тип.

И это вызывает способ группировки слепков на основании того, что актеры действительно делает:

  • Слепки, которые сохраняют идентичность.
  • Каста, которые этого не делают.

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

Вторая группа - это все преобразования, которые влекут за собой репрезентативное изменение в объекте, то есть биты объекта, возвращаемого приведением, отличаются от битов литого объекта. Эти типы приведений - это операторы implicit и explicit, которые можно реализовать в любом классе/структуре C#.

Подробнее об этом можно узнать здесь in this SO answer.

Хорошо, все это очень интересно, но можете ли вы привести конкретные примеры? Да, конечно:

  1. Компилятор знает достаточно:

    interface IFoo { } 
    class Foo: Foo { } 
    IFoo foo = new Foo(); 
    

    Существует неявное приведение от Foo к IFoo в последнем заявлении: IFoo foo = (Foo)(new Foo());. Это литье будет успешно всегда, а компилятор знает, есть явный литой (ссылочные преобразования) от Foo до IFoo, поэтому он сделает это за вас.

  2. Я знаю лучше, чем компилятор:

    object o = "Hello"; 
    var s = (string)o; 
    

    Здесь я знаюo действительно строка и я говорю компилятор: даже если вы думаете o является объектом, поверьте мне, я знать его строку.

    Это также ссылочное преобразование. Строка Hello никоим образом не тронута, единственное, что мы меняем, это ссылка, указывающая на нее.

  3. Я знаю, что данный объект типа 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, поэтому приведение выполняется как явное. (Замечание о реализовано, это не применяется языком, его дизайнерское решение того, кто написал класс, определяющий операторы литья).

0

Вы отправляли конкретный объект, когда захотите использовать этот тип объекта. Другой способ бросить к другому типу является

SomeType x = obj as SomeType; 

Здесь вы не получите исключение, когда OBJ является недействительным. Однако вы должны сделать чек для == null.

1

Простой пример, приведенный в предыдущих версиях C#. List<T> не существует в этой версии, и для того, чтобы хранить коллекцию данных, которые вы должны были использовать необщего коллекции:

static void Main(string[] args) 
{ 
    ArrayList list = new ArrayList(); 
    list.Add(1); 
    list.Add(2); 
    list.Add(3); 

    int total = 0; 
    foreach(object item in list) 
     total += (int)item; // without casting, compiler never knows item is int 

    Console.WriteLine("Total = {0}", total); 
} 

Другим примером является действительным событий, большинство событий использовать подпись (object sender, EventArgs e). Для того, чтобы получить доступ к элементам отправителя, кнопок, например, то вам нужно бросить:

Button btn = (Button)sender; 
Console.WriteLine(btn.Text); 

Это лучшая практика для использования оператора as над нормальной отливкой, чтобы предотвратить нулевое ссылочное исключение, но выше - это просто примеры.

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