Простое заявление C # Noop - PullRequest
37 голосов
/ 03 августа 2011

Что такое простой оператор Noop в C #, который не требует реализации метода? (Впрочем, методы Inline / Lambda в порядке.)

Мой текущий вариант использования: я хочу занять блок catch для try-catch, чтобы я мог войти в него при отладке и проверить исключение.
Я знаю, что в любом случае, вероятно, мне следует обработать / записать исключение, но смысл этого упражнения не в этом.

Ответы [ 15 ]

60 голосов
/ 03 августа 2011

Если вы действительно хотите noop, то это определяет безымянное действие, которое ничего не делает, а затем вызывает его, не вызывая ничего:

((Action)(() => { }))();
50 голосов
/ 28 декабря 2013

Стандартной пустой операцией оператор / noop в c # является

;

как в:

if (true)
    ;

( соответствующая документация )

это конкретно относится к вашему варианту использования (просто установите точку останова на линии; или иным образом шаг к ней), минимален и напрямую поддерживается средой только для этой цели (так что вы, даже если вы выполняя сложные вещи, такие как просмотр скомпилированного источника, у вас не будет лишнего шума / и т. д., о котором нужно беспокоиться из-за компилятора / оптимизатора / и т. д. напоминание, чтобы вычистить его из кода, когда вы закончите отладку / отправку в производство

16 голосов
/ 03 августа 2011

Если вы хотите взломать метод, вы можете жестко закодировать точку останова:

System.Diagnostics.Debugger.Break();

В качестве альтернативы, если вы не компилируете в режиме релиза, следующая строка выдаст IL, который вы можете разорвать:

var a = 1;

Вы также можете написать Debug.Break (), специфичный для вашей машины:

[Conditional("DEBUG")]
[Obsolete("Please remove me before checkin.")]
public static void Break()
{
    #IF DEBUG
    if (Dns.GetHostName() == "PROTECTORONE")
        Debugger.Break();
    #ENDIF
}

Обратите внимание, что из-за [Conditional("DEBUG")] этот метод не будет вызываться на сайтах вызовов во время сборки RELEASE.

7 голосов
/ 09 мая 2013

Вы можете просто написать:

catch {
    ;
}

Пустой оператор с одной точкой с запятой - это C # NOOP.

7 голосов
/ 03 августа 2011

Вы можете написать функцию, которая ничего не делает.

public static void Noop()
{
}
5 голосов
/ 03 августа 2011

Как насчет:

GC.KeepAlive(e);

, где e - это переменная исключения?

(Я не пробовал ставить точку останова в самом объявлении catch. Такое чувство, что вы должен быть в состоянии сделать это, именно по этой причине. Но работает ли это или нет, это другой вопрос.)

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

"".AsEnumerable();
4 голосов
/ 26 июня 2016

Стандартной пустой операцией оператор / noop в C # является ;, как в if (true) ;.
- черничные поля

Но с использованием этого стандартного ; в качестве ветви оператора if заставляет MS Visual Studio 2010 отображать предупреждение: «Возможно, ошибочное пустое выражение». (Предупреждение CS0642, хотя VS2010 не сообщает мне об этом или не ссылается на фактическую справку для предупреждения.)

Хуже того, Спецификация языка MSDN C # не упоминает, что фактически кодирует , что этот пустой оператор как ветвь оператора if вызывает предупреждение CS0642 "Возможная ошибочная пустая инструкция". (Предупреждение, потому что это «плохая форма», потенциально неоднозначная.)

Хуже того, похоже, что VS2010 не дает возможности аккуратно подавить отдельное предупреждение. Я должен был бы вставить #pragma warning disable CS0642 перед строкой (ами) и [опционально] #pragma warning disable CS0642 после. Для меня это страшнее, чем предупреждение. Я бы лучше использовал { } вместо ;. (Я мог бы использовать переопределение, которое немного менее уродливо.)

Я искал здесь "C # no-op", потому что я хотел альтернативу "пустому выражению", чтобы избавиться от этого предупреждения. Мне не нужен контрольно-пропускной пункт. Я просто хочу сделать [абсолютно] ничего, что не является двусмысленным, как «пустое утверждение».

Альтернатива не должна вызывать НЕКОТОРОЕ ДРУГОЕ предупреждение. int u; не годится, потому что вызывает предупреждение «Переменная 'u' объявлена, но никогда не используется". int u = 0; не годится, потому что вызывает предупреждение «Переменная 'u' назначена, но ее значение никогда не используется".

Если бы noop; (или подобное) было добавлено как однозначное пустое утверждение (НЕ определение макроса), это было бы здорово.

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

Когда ветвь является только одним оператором, я часто опускаю окружающие { и } ЛИНИИ, потому что они не нужны, и они растягивают код по вертикали, затрудняя его чтение. Несоответствие в языке состоит в том, что я не могу опустить окружающие { и } ЛИНИИ, когда они окружают НУЛЕВЫЕ операторы. Я могу сжать две строки до { } на одной линии, но это противоречиво. Я думаю, что ; на линии - самое лучшее решение, и оно НЕ должно вызывать предупреждение на [неустановленных] основаниях "плохой формы". Я думаю, что предупреждение CS0642 должно было по умолчанию выключено. Я думаю, что следующий код должен быть приемлемым как есть:

if (condition1)
  action1;
else if (condition2)
  ;  // (do nothing)
else if (condition3)
  action3;
else if (condition4)
  ;  // (do nothing)
else if (condition5)
  action5;
else
  action99;

(Я пожаловался, что не смог написать это как комментарий, потому что у меня еще не было «50 репутаций, чтобы комментировать». Теперь, когда я могу комментировать, на 2K байтах, это слишком долго для комментария на 1.5K байтов, поэтому он остается здесь.)

4 голосов
/ 15 сентября 2011

Зачем чрезмерно проектировать это?

var x = 0;

отлично работает:)

4 голосов
/ 03 августа 2011

В дополнение к ответам, которые прямо отвечают на вопрос.


Если вы хотите просто разбить, то вы всегда можете поставить точку останова на открытии { или закрытии } блока catch.

3 голосов
/ 21 января 2015

Я знаю, что это старый вопрос, и, технически, этот ответ не относится к варианту использования спрашивающего.Однако в CIL есть инструкция NOOP, которая равна nop.В качестве эксперимента возьмите следующее приложение CIL.

.assembly extern mscorlib {}

.assembly Test
{
    .ver 1:0:1:0
}
.module test.exe

.method static void main() cil managed
{
    .maxstack 1
    .entrypoint

    nop
    nop
    nop
    nop

    ret
}

Если вы компилируете приложение и декомпилируете его с помощью инструмента, подобного ILSpy, в C #, это содержимое метода main ():

static void main()
{
}

Как видите, там ничего нет.Однако, если мы хотим убедиться, что компилятор CIL не оптимизировал эти операторы nop, мы можем просмотреть наше приложение в декомпилированном коде IL в ILSpy, и вот что мы видим для основного метода:

.method static privatescope 
    void main$PST06000001 () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 5 (0x5)
    .maxstack 1
    .entrypoint

    IL_0000: nop
    IL_0001: nop
    IL_0002: nop
    IL_0003: nop
    IL_0004: ret
} // end of method '<Module>'::main

CIL, безусловно, компилирует инструкции nop в сборку.Поскольку в C # нет реализации этой инструкции, эти команды nop не отображаются в разобранном коде C #.

У меня нет лицензии на Reflector, но я думаю, что если вы декомпилируете эти двоичные файлы с помощью Reflector, вы получите аналогичный вывод для C #.

...