Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Нет.

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

public bool SomeMethod(out string input)
{
    ...
}

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

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

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

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

Ответ 3

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

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

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

public string foo(string value, OptionalOut<int> outResult = null)
{
    // .. do something

    if (outResult != null) {
        outResult.Result = 100;
    }

    return value;
}

public void bar ()
{
    string str = "bar";

    string result;
    OptionalOut<int> optional = new OptionalOut<int> ();

    // 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);
}

Ответ 4

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

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

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

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 в С#, то это позволит вам сделать именно это.

Ответ 5

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

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

PS, если вас также смущает часть "out var x", прочитайте также новую ссылку "Out Variables" по ссылке.

Ответ 6

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

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

public string foo(string value, Action<int> 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 (компилятор обертывает его в классе замыкания, а не мы, обертывая его явно в пользовательском классе).

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

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

Ответ 7

Используйте перегруженный метод без параметра out, чтобы вызвать метод с параметром out для С# 6.0 и ниже. Я не уверен, почему С# 7.0 для .NET Core даже является правильным ответом для этой темы, когда его специально спросили, может ли С# 4.0 иметь необязательный параметр out. Ответ - нет!

Ответ 8

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

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

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

Ответ 9

void foo(ref int? n)
{
    return null;
}