В С++ существует множество способов написать код, который компилируется, но дает undefined поведение (Wikipedia). Есть что-то подобное в С#? Можем ли мы написать код на С#, который компилируется, но имеет поведение undefined?
Код с поведением undefined в С#
Ответ 1
Как отмечали другие, почти все, что содержится в "небезопасном" блоке, может дать поведение, определяемое реализацией; злоупотребление небезопасными блоками позволяет вам изменить байты кода, которые составляют само время выполнения, и поэтому все ставки отключены.
Угловой случай целочисленного деления имеет поведение, определенное реализацией.
Бросание исключения и никогда не ловящее его вызывает поведение, определяемое реализацией - завершение процесса, запуск отладчика и т.д.
В С# существует ряд других ситуаций, когда мы вынуждены испускать код, который имеет поведение, определенное реализацией. Например, эта ситуация:
http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
Однако ситуации, в которых безопасная, хорошо управляемая программа С# имеет поведение, определяемое реализацией, должно быть довольно редко.
Ответ 2
Да! Существует даже в безопасном контексте! (Ну, это реализация определена как undefined, по крайней мере)
Здесь один из Marek Safar и VSadov в Проблемы с Roslyn. Между С# и CLI существует несоответствие в отношении bool
,
С# считает, что существует только один вид true
и один вид false
.
CLI считает, что false
- это байт, содержащий 0, а все остальные значения true
.
Это несоответствие означает, что мы можем принудить С# делать некоторые a (незначительно) интересные вещи вещи:
//non-standard bool
//We're setting a bool value to a byte value of 5.
var a = new bool[1];
Buffer.SetByte(a, 0, 5);
//non-standard bool
//We're setting a bool value to a byte value of 10.
var b = new bool[1];
Buffer.SetByte(b, 0, 10);
//Both are true.
Console.WriteLine(a[0]);
Console.WriteLine(b[0]);
//But they are not the same true.
Console.WriteLine(a[0] == b[0]);
Вышеуказанные выходы:
true
true
false
Интересно, что отладчик не согласен (должен оценивать правду по-другому?)
В любом случае вывод, который, по-видимому, пришел к команде С# (выделено мной):
т.е. язык останется совершенно безразличным к нестандартным правилам. Конкретная реализация (как в MS С# на CIL) признает существование нестандартных bools и определяет их поведение как undefined
Ответ 3
Глядя на Wiki, ситуации, в которых происходит поведение undefined, либо не разрешены, либо генерируют исключение в С#.
Однако в небезопасном коде поведение undefined, я считаю возможным, поскольку это позволяет использовать указатели и т.д.
Изменить: похоже, что я прав: http://msdn.microsoft.com/en-us/library/aa664771%28VS.71%29.aspx
Имеет пример поведения undefined в С#
Ответ 4
В соответствии с документом ECMA-334 (стр. 473):
Программа, которая не содержит появление небезопасного модификатора не может выставлять undefinedповедение.
Это способствует "реализации" в наихудшем случае, см. ответ Эрика Липперта.
Ответ 5
Многие и подпрограммы имеют требования, которые можно суммировать как:
-
При предоставлении достоверных данных произведите корректный вывод.
-
Воздерживаться от запуска ядерных ракет или отрицания законов времени и причинности даже при наличии недопустимого ввода.
Одной из основных целей разработки Java и .NET-языков является то, что, если код не использует определенные, которые помечены как "небезопасные", особых усилий, как правило, не требуется для удовлетворения второго ограничения выше [хотя некоторые виды поведения, связанные с мусором коллекция и Finalize
могут быть немного странными с точки зрения времени/причинности, их можно охарактеризовать как исключения из нормальных правил причинности, а не их полного отзыва]. Эта ситуация сильно отличается от ситуации на C, где многие виды зависящих от данных ошибок (например, переполнение целочисленных чисел) могут приводить к тому, что компиляторы ведут себя произвольным образом, включая любые предположения, необходимые для предотвращения переполнения. Поистине ужасные виды Undefined Поведения, которые поощряются в гипермодернистской философии C, не существуют на С# или других языках .NET за пределами "небезопасных" блоков.
Ответ 6
В общем, я бы сказал, нет.
Используйте автоматическую переменную перед ее инициализацией.
Все переменные должны быть инициализированы. Если не возникает исключение.
Деление на ноль
Выбрасывается исключение.
Индексирование массива за пределами границ
Исключение выбрано
Как указал Aequitarum Custos, вы можете использовать небезопасный код. Опять же, это не действительно С#, вы явно отказываетесь от среды С#.
Ответ 7
Не совсем в смысле Wiki, но я полагаю, что самый очевидный пример, который приходит мне на ум, - это просто написать какой-то многопоточный код, но тогда это так на любом языке.