Лучшая практика: возвращаемое значение функции или выходные параметры byref? - PullRequest
3 голосов
/ 29 октября 2008

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

Является ли лучший подход к:

  1. Напишите функцию, которая возвращает false, если не найден, true, если найден, и найденный номер строки в качестве параметра byref / output, или
  2. Напишите функцию, которая возвращает int и возвращает -999, если значение строки не найдено, или номер строки, если оно есть?

Ответы [ 8 ]

13 голосов
/ 29 октября 2008

Лично я бы не стал делать с этим именем метода.

Вместо этого я бы сделал два метода:

TryFindSpecificRow
FindSpecificRow

Это будет соответствовать шаблону Int32.Parse / TryParse, и в C # они могут выглядеть так:

public static Boolean TryFindSpecificRow(DataTable table, out Int32 rowNumber)
{
    if (row-can-be-found)
    {
        rowNumber = index-of-row-that-was-found;
        return true;
    }
    else
    {
        rowNumber = 0; // this value will not be used anyway
        return false;
    }
}

public static Int32 FindSpecificRow(DataTable table)
{
    Int32 rowNumber;


    if (TryFindSpecificRow(table, out rowNumber))
        return rowNumber;
    else
        throw new RowNotFoundException(String.Format("Row {0} was not found", rowNumber));
}

Редактировать: Изменено, чтобы быть более подходящим для вопроса.

3 голосов
/ 29 октября 2008

Вы также можете определить возвращаемое значение как Nullable и ничего не возвращать, если ничего не найдено.

3 голосов
/ 29 октября 2008

функции, которые не работают, должны выдавать исключения.

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

Если бы мне пришлось выбирать между вашими вариантами, я бы выбрал вариант 2, но использовал бы константу, а не -999 ...

2 голосов
/ 29 октября 2008

Я бы выбрал вариант 2. Хотя я думаю, я бы просто использовал -1, а не -999.

Ричард Харрисон прав, что именованная константа лучше, чем голые -1 или -999.

1 голос
/ 29 октября 2008

Переходите к 2), но возвращайте -1 (или нулевую ссылку, если возвращаете ссылку на строку), эта идиома широко используется (в том числе с помощью функций .nets indexOf (item)), это то, что я, вероятно, буду делать .

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

Однако многое из этого связано с тем, что вы ожидаете. Должен ли предмет всегда быть там, но вы просто не знаете, где? В этом случае верните индекс как обычно и сгенерируйте ошибку / исключение, если его там нет.

1 голос
/ 29 октября 2008

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

Кажется, что значение строки, которую функция возвращает (или предоставляет ссылку), уже указывает, было ли найдено значение. Если значение не было найдено, то, по-видимому, нет смысла указывать номер строки, который не содержит значение, поэтому возвращаемое значение должно быть равно -1, или Нуль, или любому другому значению, подходящему для конкретного языка. В противном случае тот факт, что номер строки был возвращен, указывает на то, что значение было найдено.

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

0 голосов
/ 23 марта 2012

Еще несколько возможностей, которые еще не упомянуты:

// Method 1: Supports covariance; can return default<T> on failure.
T TryGetThing(ref bool success); 

// Method 2: Does not support covariance, but may allow cleaner code in some cases
// where calling code would use some particular value in in case of failure.
T TryGetThing(T DefaultValue);

// Method 3: Does not support covariance, but may allow cleaner code in some cases
// where calling code would use some particular value in case of failure, but should
// not take the time to compute that value except when necessary.
T TryGetThing(Func<T> AlternateGetMethod);

// Method 4: Does support covariance; ErrorMethod can throw if that's what should
// happen, or it can set some flag which is visible to the caller in some other way.
T TryGetThing(Action ErrorMethod);

Первый подход - обратный метод, разработанный Microsoft за несколько дней до существования поддержки ковариантных интерфейсов. Последний в некотором смысле наиболее универсален, но, вероятно, потребует создания пары новых экземпляров объекта GC (например, замыкание и делегат) каждый раз, когда он используется.

0 голосов
/ 29 октября 2008

В этом случае предмет может отсутствовать, и это нормально. Это ловушка ошибки для невыбранных значений в GridView, которые связываются с данными.

...