Лучшая практика: возвращаемое значение функции или выходные параметры byref?

StackOverflow https://stackoverflow.com/questions/246814

  •  05-07-2019
  •  | 
  •  

Вопрос

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

Это лучший подход к:

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

    Решение

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

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

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

    Изменить. Изменено, чтобы оно больше соответствовало вопросу.

    Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    // 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 (например, замыкание и делегат) каждый раз, когда он используется.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top