C # 4.0 необязательные аргументы out / ref

Предоставляет ли C # 4.0 необязательные аргументы или аргументы?

Как уже упоминалось, это просто не допускается, и я думаю, что это имеет очень хороший смысл. Однако, чтобы добавить более подробную информацию, вот цитата из спецификации C # 4.0 , раздел 21.1:

Формальные параметры конструкторов, методов, индексаторов и типов делегатов могут быть объявлены необязательными:

с фиксированным параметром:
атрибуты opt параметр-модификатор opt type identifier default-argument opt
по умолчанию аргументы:
= выражение

  • Параметр с фиксированным параметром с аргументом по умолчанию является необязательным параметром , тогда как фиксированный параметр без аргумента по умолчанию является обязательным параметром .
  • Обязательный параметр не может появиться после необязательного параметра в списке формальных параметров .
  • Параметр ref или out не может иметь аргумент по умолчанию .

Нет.

Обходным путем является перегрузка с помощью другого метода, который не имеет параметров out / ref и который просто вызывает ваш текущий метод.

 public bool SomeMethod(out string input) { ... } // new overload public bool SomeMethod() { string temp; return SomeMethod(out temp); } 

Обновление: если у вас есть C # 7.0 , вы можете упростить:

 // new overload public bool SomeMethod() { return SomeMethod(out _); // declare out as an inline discard variable } 

(Спасибо @Oskar / @Reiner за это.)

Нет, но другой большой альтернативой является использование метода общим шаблоном для необязательных параметров следующим образом:

 public class OptionalOut { public Type Result { get; set; } } 

Затем вы можете использовать его следующим образом:

 public string foo(string value, OptionalOut outResult = null) { // .. do something if (outResult != null) { outResult.Result = 100; } return value; } public void bar () { string str = "bar"; string result; OptionalOut optional = new OptionalOut (); // example: call without the optional out parameter result = foo (str); Console.WriteLine ("Output was {0} with no optional value used", result); // example: call it with optional parameter result = foo (str, optional); Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result); // example: call it with named optional parameter foo (str, outResult: optional); Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result); } 

Фактически есть способ сделать это, что разрешено C #. Это возвращается к C ++ и скорее нарушает красивую объектно-ориентированную структуру C #.

ИСПОЛЬЗУЙТЕ ЭТОТ МЕТОД С ПРЕДОСТЕРЕЖЕНИЕМ!

Вот как вы заявляете и записываете свою функцию с необязательным параметром:

 unsafe public void OptionalOutParameter(int* pOutParam = null) { int lInteger = 5; // If the parameter is NULL, the caller doesn't care about this value. if (pOutParam != null) { // If it isn't null, the caller has provided the address of an integer. *pOutParam = lInteger; // Dereference the pointer and assign the return value. } } 

Затем вызовите функцию следующим образом:

 unsafe { OptionalOutParameter(); } // does nothing int MyInteger = 0; unsafe { OptionalOutParameter(&MyInteger); } // pass in the address of MyInteger. 

Чтобы получить это для компиляции, вам нужно включить небезопасный код в параметрах проекта. Это действительно хакерское решение, которое обычно не следует использовать, но если вы используете какое-то странное, загадочное, загадочное решение, основанное на управлении, на самом деле нужен необязательный параметр out в C #, то это позволит вам сделать именно это.

ICYMI: Включенный в новые функции для C # 7.0, перечисленные здесь , теперь «сбросы» разрешены как параметры в форме _, чтобы вы могли игнорировать параметры, которые вам не нужны:

p.GetCoordinates(out var x, out _); // I only care about x

PS, если вас тоже путают с частью «out var x», прочитайте новую функцию о «Out Variables» в ссылке.

Нет, но вы можете использовать делегат (например, Action ) в качестве альтернативы.

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

 public string foo(string value, Action outResult = null) { // .. do something outResult?.Invoke(100); return value; } public void bar () { string str = "bar"; string result; int optional = 0; // example: call without the optional out parameter result = foo (str); Console.WriteLine ("Output was {0} with no optional value used", result); // example: call it with optional parameter result = foo (str, x => optional = x); Console.WriteLine ("Output was {0} with optional value of {1}", result, optional); // example: call it with named optional parameter foo (str, outResult: x => optional = x); Console.WriteLine ("Output was {0} with optional value of {1}", result, optional); } 

Это имеет то преимущество, что необязательная переменная появляется в источнике как нормальный int (компилятор обертывает его в classе замыкания, вместо того, чтобы обменивать его явно в пользовательском classе).

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

Он не подходит для всех случаев использования, но хорошо работает для моего реального использования (функция, которая предоставляет данные для единичного теста, и где для нового модульного теста необходим доступ к некоторому внутреннему состоянию, отсутствующему в возвращаемом значении).

Как насчет этого?

 public bool OptionalOutParamMethod([Optional] ref string pOutParam) { return true; } 

Вы все равно должны передать значение параметру из C #, но это необязательный параметр ref.

 void foo(ref int? n) { return null; } 
Давайте будем гением компьютера.