Исключения и специальные возвращаемые значения - PullRequest
8 голосов
/ 23 марта 2009

Какая практика лучше программировать?

Я не говорю о полной исключительности. Это больше для таких вещей, как:

list<T>.Find, где вместо ValueNotFound (пример) вы получите default(T) или ваше значение.

или

list<T>.IndexOf, где вы получите -1 или правильный индекс.

Ответы [ 15 ]

0 голосов
/ 24 марта 2009

, что я обычно делаю в этом случае, это определяю класс Option (вдохновленный F #) и расширяю IEnumerable методом TryFind (), который возвращает класс Option.

public class Option<T>
{
    string _msg = "";
    T _item;

    public bool IsNone
    {
        get { return _msg != "" ? true : false; }
    }

    public string Msg
    {
        get { return _msg; }
    }

    internal Option(T item)
    {
        this._item = item;
        this._msg = "";
    }

    internal Option(string msg)
    {
        if (String.IsNullOrEmpty(msg))
            throw new ArgumentNullException("msg");

        this._msg = msg;
    }

    internal T Get()
    {
        if (this.IsNone)
            throw new Exception("Cannot call Get on a NONE instance.");

        return this._item;
    }

    public override string ToString()
    {
        if (this.IsNone)
            return String.Format("IsNone : {0}, {1}", this.IsNone, typeof(T).Name);

        else 
            return String.Format("IsNone : {0}, {1}, {2}", this.IsNone, typeof(T).Name, this._item.ToString());
    }

}

Тогда вы можете использовать его как

var optionItem = list.TryFind(x => trueorFalseTest() );
if (!optionItem.IsNone)
   var myItem = optionItem.Get();

Таким образом, независимо от того, существует элемент или нет, коллекция просматривается только один раз.

0 голосов
/ 24 марта 2009

Во-первых, мне не очень нравится опция default(T): что, если у вас есть список int, где 0 (предположительно, это значение по умолчанию int; я не использую C #) такое вполне допустимое значение?

(Извиняюсь за синтаксис Java, но если бы я попытался угадать C #, я бы где-нибудь напутал :))

class Maybe<T> {
    public Maybe() {
        set = false;
        value = null;
    }

    public Maybe(T value) {
        set = true;
        this.value = value;
    }

    public T get(T defaultVal) {
        if (set)
            return value;
        return defaultVal;
    }

    private boolean set;
    private T value;
}

Тогда, конечно, Find вернет Maybe<T>, и вызывающий выберет какое-то значение, которое будет разумным значением по умолчанию в этом контексте . Возможно, вы могли бы добавить getDefault для удобства, когда default(T) является правильным ответом, конечно.

Для IndexOf, однако, -1 является разумным значением для этого, поскольку действительные значения, очевидно, всегда> = 0, поэтому я бы просто сделал это.

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

Исключением должно быть что-то "исключительное". Так что, если вы звоните Find и ожидаете что-то найти, несмотря ни на что, генерировать исключение, если вы не нашли что-либо, - хорошее поведение.

Если, однако, это нормальный процесс, когда вы что-то иногда не находите, генерировать исключение - это плохо.

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

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

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

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

С чисто дизайнерской точки зрения я предпочитаю создавать исключения, когда происходит «исключительная» вещь, например ключ, который вы просили, не найден. Основная причина в том, что это облегчает жизнь потребителям - им не нужно проверять значение после каждого вызова вашей функции. Мне также нравятся функции TrySomething, потому что тогда пользователь может явно проверить, была ли операция успешной.

К сожалению, исключения в .Net довольно дороги (из моего опыта обычно требуется около 50 мсек, чтобы сгенерировать одно), поэтому с практической точки зрения вы можете захотеть вернуть одно из этих значений по умолчанию вместо генерирования исключения, особенно в программировании с графическим интерфейсом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...