Условное поведение с пользовательскими сигналами ошибок


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

var error = DoSomething();

if( !error.Success )
    return error;

return DoSomethingElse();

Я хотел бы сделать примерно следующее:

DoSomething().ReturnIfError();
return DoSomethingElse();

Я знаю, что некоторые языки, такие как Ruby, поддерживают конструкцию "return if" - есть ли она такая вещь в C#, или это было бы возможно сделать в методе расширения?

2 2

2 ответа:

Это не то, что можно красиво взломать с помощью методов расширения.

Во втором примере, который вы привели (с теоретическим методом сцепления), вы бы это сделали...

  • вызов DoSomething
  • если DoSomething ошибка, вызовите ReturnIfError
  • затем вызовите DoSomethingElse

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

Предполагая, что это то, что вы действительно хотите сделать, то следующий код может сделать это (не то, что я рекомендую!).

using System;

namespace ConsoleApplication6
{
    public static class ClassUtility
    {
        public static void CallOnError<TIn>(this TIn value, Func<TIn, bool> fn, Action<TIn> errorFn)
            where TIn : class
        {
            if (!fn(value))
            {
                errorFn(value);
            }
        }
    }

    public class TestClass
    {
        public bool FirstCall(bool value)
        {
            Console.WriteLine("First call.");
            return value;
        }

        public void SecondCall()
        {
            Console.WriteLine("Second call.");
        }

        public void ThirdCall()
        {
            Console.WriteLine("Third call.");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var testClass = new TestClass();

            testClass.CallOnError(tc => tc.FirstCall(false),
                                  tc2 => tc2.SecondCall());

            testClass.CallOnError(tc => tc.FirstCall(true),
                                  tc2 => tc2.SecondCall());

            testClass.ThirdCall();

            Console.ReadLine();
        }
    }
}

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