2012-04-30 4 views
16

Мне нужно создать гетерогенный объект List объектов (нестандартных классов). Моя первая мысль заключалась в том, чтобы создать List<ISomeMarkerInterface>, но я быстро понял, что это не то, что я хочу. Моя следующая мысль была List<dynamic>, и это, казалось, не плохая идея. Тем не менее, я занимался некоторыми исследованиями и наткнулся на это article about boxing and unboxing, и в этом примере они делают в основном то, что я хочу, используя List<Object>.Список <Object> vs Список <dynamic>

Помимо того, что dynamic будет оценен во время выполнения и Object во время компиляции, в чем заключается разница между List<dynamic> и List<Object>? Разве это не одно и то же?

+2

Почему вам нужно хранить гетерогенные объекты в одном списке? Просто любопытно ... –

+0

вам следует искать динамический объект vs, проверить этот поток, он, вероятно, отвечает на ваш ответ http://stackoverflow.com/questions/3442821/dynamic-vs-object-type – Habib

+0

У меня есть класс, где один свойств - это набор элементов, относящихся к этому классу, которые не являются одним и тем же типом, но имеют значение как группа. – Jason

ответ

19

В C#: объект, var и динамика есть 3 "общих" типа (хотя не все являются реальными типами).

Объект

Фактический тип, как и любой другой тип, с одним специальным правилом: если тип не наследует, он наследует от объекта. Из этого следует, что все типов наследуют от объект, прямо или косвенно.

Адрес: объект тип. Объект может иметь тип объект, а тип имеет свои методы, такие как ToString(). Поскольку все наследуется от объекта, все может быть upcast в объект. При назначении объекта в качестве объекта ссылки, вы делаете так же, как приведение к базовому типу, когда вы назначаете слона объект типа к животным ссылки, где слон наследуется от животных.

SomeType x = new SomeType(); 
object obj = x; 
obj.DoSomething(); 
  • OBJ трактуется как тип объекта во время компиляции, и будет иметь тип объекта во время выполнения (что логично, поскольку он является фактический тип - OBJ объявлен как объект так может быть только этого типа)
  • obj.DoSomething() вызовет ошибку во время компиляции, так как Ob ject не имеет этого метода, независимо от того, имеет ли его тип SomeType.

Var

Это не фактический тип, это просто сокращение для «компилятора, выяснить тип для меня, основываясь на правой стороне уступка».

SomeType x = new SomeType(); 
var obj = x; 
obj.DoSomething(); 
  • OBJ рассматривается как тип SomeType во время компиляции, и будет типа SomeType во время выполнения, так же, как если бы вы написали «SomeType» вместо «вар» ,
  • если SomeType имеет метод DoSomething(), этот код будет работать
  • если SomeType не имеет метода, то код будет вызывать ошибку времени компиляции

Динамический

Это тип, который сообщает компилятору отключить проверку типа компиляции по переменной. Объект рассматривается как имеющий тип динамический во время компиляции и времени выполнения.

SomeType x = new SomeType(); 
dynamic obj = x; 
obj.DoSomething(); 
  • OBJ имеет тип динамического во время компиляции и время выполнения
  • если SomeType имеет метод DoSomething(), этот код будет работать
  • если SomeType Безразлично» t, этот метод будет компилироваться, но генерирует исключение во время выполнения
  • нет е, что динамический может вызвать исключения очень легко, если использовать небрежно:

    public void f(dynamic x) 
    { 
        x.DoSomething(); 
    } 
    

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

Примечание: объект, на который ссылается, никогда не изменяет его тип, конечно. В то время как obj может быть объект, x, что он относится к прежнему SomeType.

+4

- 1 для того, чтобы сказать, что 'dynamic' не является фактическим типом (очень отличается от' var', который _isn't_ фактического типа, как вы правильно говорите). 'dynamic' наиболее определенно является типом в C#, это даже тип _static_, но объект типа' dynamic' будет обходить проверку статического типа. Ознакомьтесь с §4.7 Спецификации языка C# или этой ссылкой (http://msdn.microsoft.com/en-us/library/dd264736.aspx) для получения дополнительной информации. – Nailuj

+0

К сожалению, я исправил его. Сначала я должен был проверить. : D Я, хотя динамика сразу же была разрешена к соответствующему типу во время выполнения задания и никогда не была набрана как «динамическая», но, видимо, это не так. – svinja

+1

Не больше -1 :) – Nailuj

2

Разница в том, что если вы используете объект и пытаетесь получить доступ к некоторому члену вашего объекта, это будет ошибка времени компиляции (поскольку объект не имеет этого члена). Чтобы работать, вам нужно знать, что такое тип и бросить его.

С динамикой вы можете получить доступ к любому члену - без ошибки времени компиляции. Если член не существует во время выполнения, это будет ошибка времени выполнения. Это путь, если вы знаете, что у ваших однородных объектов есть один и тот же член, например.

Однако, если это так, есть еще одно более четкое решение: вы можете определить интерфейс с этим членом, а затем сделать все ваши стандартные объекты реализованы, а ваш список может быть List<IYourInterface>.

Помните, что динамическая динамика может быть немного хуже из-за динамического разрешения.

+0

с помощью динамического, можете ли вы проверить существование члена и продолжить его, если он не существует, не выкидывая ошибку? вроде как в javascript, как вы можете сделать что-то вроде 'if (data.something) {}'? – Jason

+1

Это называется отражением. Вы можете использовать его с или без * dynamic *. Посмотрите на GetType(), GetMethod() и т. Д. – svinja

+0

+1, если вы идете по маршруту отражения, вы можете просто использовать Object (но я бы по-прежнему рекомендовал интерфейс маркера) – MattDavey

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