Если вы недавно изменили innodb_log_file_size
, попытайтесь восстановить предыдущее значение, которое сработало.
В принципе, дисперсия применяется, когда CLR может гарантировать, что ей не нужно делать какие-либо репрезентативные изменения к значениям. Все ссылки одинаковы, поэтому вы можете использовать IEnumerable<string>
как IEnumerable<object>
без каких-либо изменений в представлении; сам собственный код не обязательно должен знать, что вы делаете со значениями, если инфраструктура гарантировала, что он определенно будет действительным.
Для типов значений, которые не work - для обработки IEnumerable<int>
как IEnumerable<object>
, код, использующий последовательность, должен был бы знать, следует ли выполнять преобразование бокса или нет.
Возможно, вы захотите прочитать блог Эрика Липперта пост по представлению и идентичности для более подробной информации по этой теме в целом.
EDIT: перечитав блог в блоге Эрика, это как минимум примерно тождество как представление, хотя эти два связаны. В частности:
Вот почему ковариантные и контравариантные преобразования интерфейса и типов делегатов требуют, чтобы все переменные аргументы типа были ссылочными типами. Чтобы гарантировать, что вариантное преобразование ссылок всегда сохраняется с сохранением идентичности, все преобразования, связанные с аргументами типа, также должны сохраняться в идентичности. Самый простой способ гарантировать, что все нетривиальные преобразования в аргументах типа сохраняют сохранение идентичности, - это ограничение их ссылок на ссылки.
blockquote>
Я думаю, что все начинается с определения LSP
(Принцип замещения Лискова), который climes:
, если q (x) - свойство, доказуемое об объектах x типа T, то q ( y) должно быть истинным для объектов y типа S, где S является подтипом T.
blockquote>Но типы значений, например
int
, не могут быть замененыobject
вC#
. Доказательство очень просто:int myInt = new int(); object obj1 = myInt ; object obj2 = myInt ; return ReferenceEquals(obj1, obj2);
Это возвращает
false
, даже если мы назначим ту же «ссылку» на объект.
int
не является подтипом object
, поэтому принцип не применяется. Ваше & quot; доказательство & quot; опирается на промежуточное представление Integer
, которое является подтипом object
и для которого язык имеет неявное преобразование (object obj1=myInt;
фактически расширен до object obj1=new Integer(myInt)
;).
– André Caron
17 September 2012 в 13:05
int
не является подтипом object
. Более того, LSP не применяется, потому что myInt
, obj1
и obj2
относятся к трем различным объектам: одному int
и двум (скрытым) Integer
s.
– André Caron
17 September 2012 в 18:13
int
является псевдонимом для BCL System.Int32
, который на самом деле является подтипом object
(псевдоним System.Object
). Фактически, базовый класс int
- System.ValueType
, базовый класс которого System.Object
. Попробуйте оценить следующее выражение и посмотрите: typeof(int).BaseType.BaseType
. Причина, по которой ReferenceEquals
возвращает false, заключается в том, что int
помещается в два отдельных окна, а идентификатор каждого окна отличается для любого другого поля. Таким образом, две операции по боксу всегда дают два объекта, которые никогда не идентичны, независимо от значения в коробке.
– Allon Guralnek
18 September 2012 в 22:43
System.Int32
или List<String>.Enumerator
) фактически представляет два вида вещей: тип местоположения хранилища и тип объекта кучи (иногда называемый «тип в штучной упаковке»). Место хранения, чьи типы получены из System.ValueType
, будет содержать первое; объекты кучи, типы которых аналогичным образом будут удерживать последний. На большинстве языков существует расширяющаяся личность из прежней последней и сужение от последнего к первому. Обратите внимание, что, в то время как типы значений в штучной упаковке имеют дескриптор того же типа, что и места хранения типа значения, ...
– supercat
20 November 2012 в 18:37
Он доходит до детали реализации: типы значений реализуются по-разному для ссылочных типов.
Если вы принудительно применяете типы значений как ссылочные типы (то есть оставьте их, например, обратившись к ним через интерфейс), вы можете получить дисперсию.
Самый простой способ увидеть разницу - просто рассмотреть Array
: массив типов значений объединяется в память смежно (напрямую), где в качестве массива В ссылочных типах всегда имеется ссылка (указатель) в памяти; объекты, на которые указываются, выделены отдельно.
Другая (связанная) проблема (*) заключается в том, что (почти) все типы ссылок имеют одинаковое представление для целей дисперсии, и много кода не нужно знать о разница между типами, поэтому возможна совпадение и противоречие (и легко реализуются - часто просто за счет исключения дополнительной проверки типов).
(*) Это может рассматриваться как одна и та же проблема. .
Возможно, вам легче понять, если вы думаете о базовом представлении (хотя это действительно детализация реализации). Вот набор строк:
IEnumerable<string> strings = new[] { "A", "B", "C" };
Вы можете думать о том, что strings
имеет следующее представление:
[0] : string reference -> "A" [1] : string reference -> "B" [2] : string reference -> "C"
Это набор из трех элементов, каждый являясь ссылкой на строку. Вы можете передать это в коллекцию объектов:
IEnumerable<object> objects = (IEnumerable<object>) strings;
В основном это то же представление, за исключением того, что ссылки являются ссылками на объекты:
[0] : object reference -> "A" [1] : object reference -> "B" [2] : object reference -> "C"
Представление такое же. Ссылки рассматриваются только по-разному; вы больше не можете получить доступ к свойству string.Length
, но вы все равно можете вызвать object.GetHashCode()
. Сравните это с коллекцией ints:
IEnumerable<int> ints = new[] { 1, 2, 3 };
[0] : int = 1 [1] : int = 2 [2] : int = 3
Чтобы преобразовать это в IEnumerable<object>
, данные должны быть преобразованы путем бокса ints:
[0] : object reference -> 1 [1] : object reference -> 2 [2] : object reference -> 3
Это преобразование требует больше, чем литье.
this
относится к структуре, поля которой накладываются на те объекты кучи, которые хранят ее, а не ссылаются на объект, который их удерживает. Нет чистого пути для экземпляра типа boxed value, чтобы получить ссылку на объект кучи-оболочки.
– supercat
21 November 2012 в 00:31
int
не является подтипомobject
, поэтому ковариантное преобразование не требуется. Напротив,IEnumerable<Integer>
будет ковариантным типом возврата. – André Caron 17 September 2012 в 13:07int
не является подтипомobject
. Следствием этого является тот факт, что требуется репрезентативное изменение. – André Caron 17 September 2012 в 18:16