Почему мой массив C# теряет информацию о знаке типа, когда брошено для возражения?

Если установлено, что просто проверка navigator.userAgent не всегда надежна. Большая надежность может быть достигнута также путем проверки navigator.platform. Простая модификация предыдущего ответа, кажется, работает лучше:

if (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ||
   (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.platform))) {
    // some code...
}
42
задан John Saunders 29 August 2010 в 03:36
поделиться

4 ответа

ОБНОВЛЕНИЕ: Я использовал этот вопрос как основу для записи в блоге, здесь:

http://blogs.msdn.com/ericlippert/archive/2009/09/24 /why-is-covariance-of-value-typed-arrays-inconsistent.aspx

См. комментарии в блоге для более подробного обсуждения этой проблемы. Спасибо за отличный вопрос!


Вы наткнулись на интересное и досадное несоответствие между системой типов CLI и системой типов C #.

В CLI есть концепция «совместимости по назначению». Если значение x известного типа данных S является «совместимым по назначению» с конкретным местом хранения y известного типа данных T, то вы можете сохранить x в y. Если нет, то такой код не поддается проверке, и проверяющий его запретит.

Система типов CLI говорит, например, что подтипы ссылочного типа совместимы по присваиванию с супертипами ссылочного типа. Если у вас есть строка, вы можете сохранить ее в переменной типа object, потому что оба являются ссылочными типами, а строка - подтипом объекта. Но обратное неверно; супертипы несовместимы с подтипами по присваиванию. Вы не можете вставить что-то, что только известно как объект, в переменную типа string без предварительного преобразования.

В основном «совместимость с присваиванием» означает «имеет смысл вставить именно эти биты в эту переменную». Присваивание исходного значения целевой переменной должно «сохранять представление». Подробности см. В моей статье:

http://ericlippert.com/2009/03/03/presentation-and-identity/

Одно из правил интерфейса командной строки гласит: «Если X является присваиванием, совместимым с Y ,

Но это законно в CLI. Итак, теперь мы стоим перед выбором.

1) Реализовать "is", чтобы, когда компилятор не может определить ответ статически, он фактически вызывает метод, который проверяет все правила C # на возможность преобразования с сохранением идентичности. Это медленно, и в 99,9% случаев соответствует правилам CLR. Но мы принимаем удар по производительности, чтобы быть на 100% совместимым с правилами C #.

2) Реализуем "is", чтобы, когда компилятор не может определить ответ статически, он выполнял невероятно быструю проверку совместимости назначения CLR и смиритесь с тем фактом, что здесь говорится, что uint [] является int [], хотя на самом деле это не было бы законным в C #.

Мы выбрали последнее. К сожалению, спецификации C # и CLI расходятся во мнениях по этому второстепенному вопросу, но мы готовы мириться с несогласованностью.

66
ответ дан 26 November 2019 в 23:42
поделиться

Провести фрагмент через Reflector:

sbyte[] foo = new sbyte[10];
object bar = foo;
Console.WriteLine("{0} {1} {2} {3}", new object[] { foo != null, false, bar is sbyte[], bar is byte[] });

Компилятор C # оптимизирует первые два сравнения ( foo is sbyte [] и foo is byte [] ). Как видите, они оптимизированы для foo! = Null и просто всегда false .

9
ответ дан 26 November 2019 в 23:42
поделиться

Также интересно:

    sbyte[] foo = new sbyte[] { -1 };
    var x = foo as byte[];    // doesn't compile
    object bar = foo;
    var f = bar as byte[];    // succeeds
    var g = f[0];             // g = 255
5
ответ дан 26 November 2019 в 23:42
поделиться

Несомненно, вывод правильный. bar "равно" sbyte [] и byte [], потому что он совместим с обоими, поскольку bar является просто объектом, тогда он "может быть" либо со знаком, либо без знака.

"is" определяется как "выражение может быть приведение к типу ".

0
ответ дан 26 November 2019 в 23:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: