Вот очень читаемая функция vimscript, которая хорошо справляется со всеми случаями,
:bd
(если только одно окно, просто вызовите его!), выполните предупреждение и ничего не делать, если буфер модифицирован. если нет другого буфера, создайте его через :enew
. если существует альтернативный буфер и в buffer-list
, переключитесь на него, иначе идите дальше, через :bn
. nnoremap <Leader>b :call DeleteCurBufferNotCloseWindow()<CR> func! DeleteCurBufferNotCloseWindow() abort if &modified echohl ErrorMsg echom "E89: no write since last change" echohl None elseif winnr('$') == 1 bd else " multiple window let oldbuf = bufnr('%') let oldwin = winnr() while 1 " all windows that display oldbuf will remain open if buflisted(bufnr('#')) b# else bn let curbuf = bufnr('%') if curbuf == oldbuf enew " oldbuf is the only buffer, create one endif endif let win = bufwinnr(oldbuf) if win == -1 break else " there are other window that display oldbuf exec win 'wincmd w' endif endwhile " delete oldbuf and restore window to oldwin exec oldbuf 'bd' exec oldwin 'wincmd w' endif endfunc
Потому что вы можете переопределить operator ==
, чтобы вернуть истину для этого случая.
public class Foo
{
public void Test()
{
Console.WriteLine(this == null);
}
public static bool operator ==(Foo a, Foo b)
{
return true;
}
public static bool operator !=(Foo a, Foo b)
{
return true;
}
}
Запуск new Foo (). Test ()
выведет на консоль «True».
Другой вопрос: почему компилятор не выдает предупреждение для ReferenceEquals (this, null)
? Внизу приведенной выше ссылки:
Распространенной ошибкой при перегрузках
operator ==
является использование(a == b)
,(a == null )
или(b == null)
, чтобы проверить равенство ссылок. Вместо этого это приводит к вызову перегруженного оператора==
, что вызывает бесконечный цикл. ИспользуйтеReferenceEquals
или приведите тип к Object, чтобы избежать цикла.
Что на может ответить ответ @Aaronaught. И именно поэтому вы должны делать (object) x == null
или ReferenceEquals (x, null)
, а не выполнять простой x == null
, когда вы проверяете наличие нулевых ссылок. Если, конечно, вы не уверены, что оператор ==
не перегружен.
На самом деле, условие действительно может быть выполнено, по крайней мере в Visual Studio 2008. Они исправили это поведение в VS 2010, но не исключено, что существует и другой способ создания такого условия.
(tl;dr версия - в C# 3.5 законно ссылаться на this
из анонимной функции, переданной в качестве аргумента конструктора, но если вы действительно попытаетесь это использовать, вы обнаружите, что this
является null
.)
Это также согласуется с другими предупреждениями, которые C # делает (или не делает в этом отношении), например:
if(true)
or
if(1 == 1)
Они также всегда будут иметь один и тот же результат, нет от того, что.
Вау ... Думаю, я был постыдно неправ
Я не согласен. Я думаю, вы все еще хорошо замечаете.
Компилятор знает, будет ли сравнение идти к определяемому пользователем оператору сравнения или нет, а компилятор знает, что в противном случае 'this' никогда не будет нулевым.
И действительно, компилятор отслеживает, может ли данное выражение юридически быть нулевым или нет, чтобы реализовать небольшую оптимизацию для вызовов невиртуальных методов. Если у вас есть невиртуальный метод M и вы говорите foo.M ();
, то компилятор генерирует это как «сделать виртуальный вызов M с приемником foo». Почему? Потому что мы хотим выбросить, если foo имеет значение null, а виртуальный вызов всегда выполняет нулевую проверку получателя. Невиртуальный вызов - нет; нам пришлось бы сгенерировать его как «проверить foo на null, а затем выполнить невиртуальный вызов M», что является более длинным, медленным и более раздражающим кодом.
Теперь, если мы можем уйти, не выполнив нулевую проверку, мы это сделаем. Если вы скажете this.M ()
или (new Foo ()). M ()
, то мы НЕ генерируем виртуальный вызов. Мы генерируем не виртуальный вызов без нулевой проверки, потому что знаем, что он не может быть нулевым.
Таким образом, у компилятора есть отличные данные о том, будет ли конкретное сравнение с нулевым значением иногда, всегда или никогда не будет успешным.
Тогда возникает вопрос: «Если компилятор знает, что конкретное сравнение никогда не будет успешным, почему бы не сгенерировать для него предупреждение?»
И ответ: «Иногда мы делаем, а иногда нет».
Мы поступаем в этой ситуации:
int x = 123;
if (x == null) ...
Существует оператор равенства, определенный для двух целых чисел, допускающих значение NULL. x можно преобразовать в int, допускающий значение NULL. null можно преобразовать в int, допускающий значение NULL. Таким образом, этот оператор равенства действителен, поэтому используется и, конечно же, всегда ложен. Компилятор выдает предупреждение, что выражение всегда ложно.
Однако из-за ошибки, которую мы случайно представили в C # 3, этот код НЕ выдает этого предупреждения:
Guid x = whatever;
if (x == null) ...
То же самое. Обнуляемый оператор равенства guid действителен, но предупреждение подавляется. Я не уверен, исправили ли мы эту ошибку для C # 4 или нет. Если нет, надеюсь, мы добавим его в пакет обновления.
Что касается "if (this == null)", я не знаю, почему мы не предупреждаем об этом. Это определенно кажется хорошим кандидатом на предупреждение. Наиболее вероятное объяснение состоит в том, чтобы следовать этому логическому силлогизму:
Есть бесконечно много возможностей компилятора, о которых мы еще не думали; мы не реализовали ни одного из них.
Еще одна причина не выдавать здесь предупреждения заключается в том, что мы пытаемся выдавать предупреждения для кода, который , вероятно, будет набран случайно и почти наверняка неправильным по неочевидной причине ]. "this == null" вряд ли будет введено случайно, и хотя это почти наверняка неверно, как вы отметили в формулировке вашего вопроса, это очевидно неверно.
Сравните это с нашим "guid == null" - это может произойти случайно, потому что разработчик может случайно подумать, что Guid является ссылочным типом. Руководства обычно передаются по ссылке в C ++, поэтому легко сделать эту ошибку. Код почти наверняка неверен, но он ошибочен неочевидным образом. Так что это хороший кандидат на предупреждение. (Вот почему так жаль, что это предупреждение в C # 2, но не в C # 3, из-за ошибки, которую мы ввели.)