Порядок логики C# и поведение компилятора

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

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

18
задан Bill the Lizard 24 May 2012 в 12:30
поделиться

18 ответов

C#: Слева направо и обработка остановок, если несоответствие (оценивает ко лжи) найдено.

16
ответ дан 30 November 2019 в 05:57
поделиться

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

Примечание это & и | работает и для поразрядных масок и для булевых значений и не только для битовых операций. Они названы поразрядный, но они определяются и для целых чисел и для булевых типов данных в C#.

0
ответ дан 30 November 2019 в 05:57
поделиться

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

0
ответ дан 30 November 2019 в 05:57
поделиться

@csmba:

попросили в продолжении, почему или когда будет любой использовать И вместо AndAlso (или & вместо & &): Вот пример:

if ( x.init() And y.init()) then
   x.process(y)
end 
y.doDance()

В этом случае, я хочу к init обоих X и Y. Y должен быть инициализирован для y. DoDance, чтобы смочь выполниться. Однако в init () функционируют, я делаю также некоторую дополнительную вещь как проверка, что сокет открыт, и только если это удается хорошо для обоих, я должен идти вперед и сделать x.process (y).

я полагаю, что это довольно сбивает с толку. Хотя Ваш пример работает, это не типичный случай для использования And (и я, вероятно, записал бы это по-другому для создания этого более ясным). And (& на большинстве других языков) на самом деле поразрядное - и операция. Вы использовали бы его для вычисления битовых операций, например, удаляя флаговый бит или маскируя и тестируя флаги:

Dim x As Formatting = Formatting.Bold Or Formatting.Italic
If (x And Formatting.Italic) = Formatting.Italic Then
    MsgBox("The text will be set in italic.")
End If
0
ответ дан 30 November 2019 в 05:57
поделиться

, Что такое хороший пример того, когда использовать побитовый оператор вместо "закороченной булевской переменной"?

предположим Вы имеете флаги, говорите для атрибутов файла. Предположим, что Вы определили ЧТЕНИЕ как 4, ЗАПИШИТЕ как 2, и ДОЛЖНОСТНОЕ ЛИЦО как 1. В двоичном файле это:

READ  0100  
WRITE 0010  
EXEC  0001

Каждый флаг имеет один набор битов, и каждый уникален. Побитовые операторы позволяют Вам объединить эти флаги:

flags = READ & EXEC; // value of flags is 0101
1
ответ дан 30 November 2019 в 05:57
поделиться

Скромность понятия относится к, перегрузка оператора. в операторе:

if( A && B){
    // do something
}

А оценен сначала, если он оценивает ко лжи, B никогда не оценивается. То же относится

if(A || B){
    //do something
}

, А оценен сначала, если это оценивает к истинному, B никогда не оценивается.

Это понятие, перегрузка, относится (я думаю), все языки стиля C и многие другие также.

2
ответ дан 30 November 2019 в 05:57
поделиться

Когда вещи все встроены, они выполняются слева направо.

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

, Например

a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );

Вещи происходят как это:

  • Вызов GetAddress с литералом "Orion"
  • Вызов GetSummary с литералом "Orion" и результат GetAddress
  • Вызов Foo с литералом 5 и результат GetSummary
  • Присваивает это значение a
1
ответ дан 30 November 2019 в 05:57
поделиться

Мне нравятся ответы Orion. Я добавлю две вещи:

  1. слева направо все еще применяется сначала
  2. внутреннее-к-внешнему, чтобы гарантировать, что все аргументы разрешены прежде, чем звонить, функция

Говорят, что у нас есть следующий пример:

a = Foo(5, GetSummary("Orion", GetAddress("Orion")),
           GetSummary("Chris", GetAddress("Chris")));

Вот порядок выполнения:

  1. GetAddress("Orion")
  2. GetSummary("Orion", ...)
  3. GetAddress("Chris")
  4. GetSummary("Chris", ...)
  5. Foo(...)
  6. Присваивает a

, я не могу говорить о законных требованиях C# (хотя я действительно тестировал подобный пример, использующий Моно прежде, чем записать это сообщение), но этот порядок гарантируется в Java.

И только для полноты (так как это - агностический языком поток также), существуют языки как C и C++, где порядок не гарантируется, если не будет точка последовательности. Ссылки: 1 , 2 . В ответе на вопрос потока, однако, && и || точки последовательности в C++ (если не перегружено; также см. превосходный ответ OJ). Так некоторые примеры:

  • foo() && bar()
  • foo() & bar()

В && случай, foo(), как гарантируют, будет работать прежде bar() (если последний будет выполнен вообще), так как && точка последовательности. В & случай, никакая такая гарантия не сделана (в C и C++), и действительно bar() может работать прежде foo(), или наоборот.

1
ответ дан 30 November 2019 в 05:57
поделиться

Nopes, по крайней мере, компилятор C# не работает назад (в любом & & или ||). Это слева направо.

1
ответ дан 30 November 2019 в 05:57
поделиться

Некоторые языки имеют интересные ситуации, где выражения выполняются в другом порядке. Я конкретно думаю о Ruby, но я уверен, что они одолжили его откуда-либо (вероятно, Perl).

выражения в логике останутся слева направо, но например:

puts message unless message.nil?

Вышеупомянутое оценит "message.nil?" сначала, затем если это оценивает ко лжи (если не похож, если кроме него выполняется, когда условие является ложью вместо истинного), "помещает сообщение", выполнится, который печатает содержание переменной сообщения на экран.

Это - вид интересного способа иногда структурировать Ваш код... Мне лично нравится использовать его для очень короткого 1 лайнера как вышеупомянутое.

Редактирование:

Для создания этого немного более ясным вышеупомянутое совпадает с:

unless message.nil?
  puts message
end
4
ответ дан 30 November 2019 в 05:57
поделиться

ZombieSheep мертв - на. Единственный "глюк", который мог бы ожидать, - то, что это только верно при использовании & & оператор. При использовании & оператор, оба выражения будут оценены каждый раз, независимо если один или оба оценят ко лжи.

if (amHungry & whiteCastleIsNearby)
{
   // The code will check if White Castle is nearby
   // even when I am not hungry
}

if (amHungry && whiteCastleIsNearby)
{
   // The code will only check if White Castle is nearby
   // when I am hungry
}
4
ответ дан 30 November 2019 в 05:57
поделиться

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

На языках, как C++, где можно на самом деле перегрузить поведение & & и || операторы, настоятельно рекомендовано, что Вы не делаете этого . Это вызвано тем, что при перегрузке этого поведения Вы заканчиваете тем, что вызвали оценку обеих сторон операции. Это делает две вещи:

  1. Это повреждает механизм отложенных вычислений, потому что перегрузка является функцией, которая должна быть вызвана, и следовательно оба параметра оценены прежде, чем вызвать функцию.
  2. порядок оценки упомянутых параметров не гарантируется и может быть конкретным компилятором. Следовательно объекты не вели бы себя таким же образом, как они делают в примерах, перечисленных в ответах вопроса / предыдущих ответах.

Для большего количества информации, имейте чтение книги Scott Meyers, Более эффективный C++ .Удачи!

8
ответ дан 30 November 2019 в 05:57
поделиться

Обратите внимание, что существует различие между & & и & относительно того, сколько из Вашего выражения оценен.

& & известен как закороченная булевская переменная И, и, как отмечено другими здесь, остановится рано, если результат может быть определен, прежде чем все подвыражения будут оценены.

& известен как логический побитовый оператор и будет всегда оценивать все подвыражения.

Как таковой:

if (a() && b())

будет только звонить b если возвраты верный .

однако, это:

if (a() & b())

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

Это то же различие существует для || и | операторы.

4
ответ дан 30 November 2019 в 05:57
поделиться

@shsteimer

, к которому относится скромность понятия, является перегрузкой оператора. в операторе:... A оценен сначала, если он оценивает ко лжи, B никогда не оценивается. То же относится

, Это не перегрузка оператора. Перегрузка оператора является термином, данным для разрешения Вам определить пользовательское поведение для операторов, такой как *, +, = и так далее.

Это позволило бы Вам записать свой собственный класс 'Журнала' и затем сделать

a = new Log(); // Log class overloads the + operator
a + "some string"; // Call the overloaded method - otherwise this wouldn't work because you can't normally add strings to objects.

Выполнение, это

a() || b() // be never runs if a is true

на самом деле называют Оценка Короткого замыкания

5
ответ дан 30 November 2019 в 05:57
поделиться

vb.net

if( x isNot Nothing AndAlso x.go()) then
  1. Оценка сделана оставленная праву
  2. , оператор AndAlso удостоверяется, что, только если левая сторона была ПРАВДА, правая сторона будет оценена (очень важный, так как ifx - ничто, что x.go разрушит)

, можно использовать И вместо этого ofAndAlso в vb., в этом случае, левая сторона оценена сначала также, но правая сторона будет оценена независимо от результата.

Лучшая практика: Всегда используйте AndAlso, если у Вас нет очень серьезного основания почему не к.

<час>

попросили в продолжении, почему или когда будет любой использовать И вместо AndAlso (или & вместо & &): Вот пример:

if ( x.init() And y.init()) then
   x.process(y)
end 
y.doDance()

В этом случае, я хочу к init обоих X и Y. Y должен быть инициализирован для y. DoDance, чтобы смочь выполниться. Однако в init () функционируют, я делаю также некоторую дополнительную вещь как проверка, что сокет открыт, и только если это удается хорошо, для [1 116] и , я должен идти вперед и сделать x.process (y).

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

6
ответ дан 30 November 2019 в 05:57
поделиться

"C#: Слева направо и обработка остановок, если соответствие (оценивает к истинному) найдено".

овца Зомби неправа, недостаточно представителя, чтобы вниз проголосовать за него.

вопрос о & & оператор, не || оператор.

В случае & & оценка остановится, если ЛОЖЬ будет найдена.

В случае || оценка останавливается, если TRUE найден.

9
ответ дан 30 November 2019 в 05:57
поделиться

Левые один, затем останавливается, если это является пустым.

Редактирование: В vb.net это оценит обоих и возможно бросит ошибку, если Вы не будете использовать AndAlso

2
ответ дан 30 November 2019 в 05:57
поделиться

Язык программирования D выполняет оценку слева направо с коротким замыканием , а не допускает перегрузку && и '||' операторы.

0
ответ дан 30 November 2019 в 05:57
поделиться
Другие вопросы по тегам:

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