C# try-catch-else

后端 未结 14 1459
暗喜
暗喜 2020-12-30 19:44

One thing that has bugged me with exception handling coming from Python to C# is that in C# there doesn\'t appear to be any way of specifying an else clause. For example, in

14条回答
  •  长发绾君心
    2020-12-30 20:33

    There might not be any native support for try { ... } catch { ... } else { ... } in C#, but if you are willing to shoulder the overhead of using a workaround, then the example shown below might be appealing:

    using System;
    
    public class Test
    {
        public static void Main()
        {
            Example("ksEE5A.exe");
        }
    
        public static char Example(string path) {
            var reader = default(System.IO.StreamReader);
            var line = default(string);
            var character = default(char);
            TryElse(
                delegate {
                    Console.WriteLine("Trying to open StreamReader ...");
                    reader = new System.IO.StreamReader(path);
                },
                delegate {
                    Console.WriteLine("Success!");
                    line = reader.ReadLine();
                    character = line[30];
                },
                null,
                new Case(typeof(NullReferenceException), error => {
                    Console.WriteLine("Something was null and should not have been.");
                    Console.WriteLine("The line variable could not cause this error.");
                }),
                new Case(typeof(System.IO.FileNotFoundException), error => {
                    Console.WriteLine("File could not be found:");
                    Console.WriteLine(path);
                }),
                new Case(typeof(Exception), error => {
                    Console.WriteLine("There was an error:");
                    Console.WriteLine(error);
                }));
            return character;
        }
    
        public static void TryElse(Action pyTry, Action pyElse, Action pyFinally, params Case[] pyExcept) {
            if (pyElse != null && pyExcept.Length < 1) {
                throw new ArgumentException(@"there must be exception handlers if else is specified", nameof(pyExcept));
            }
            var doElse = false;
            var savedError = default(Exception);
            try {
                try {
                    pyTry();
                    doElse = true;
                } catch (Exception error) {
                    savedError = error;
                    foreach (var handler in pyExcept) {
                        if (handler.IsMatch(error)) {
                            handler.Process(error);
                            savedError = null;
                            break;
                        }
                    }
                }
                if (doElse) {
                    pyElse();
                }
            } catch (Exception error) {
                savedError = error;
            }
            pyFinally?.Invoke();
            if (savedError != null) {
                throw savedError;
            }
        }
    }
    
    public class Case {
        private Type ExceptionType { get; }
        public Action Process { get; }
        private Func When { get; }
    
        public Case(Type exceptionType, Action handler, Func when = null) {
            if (!typeof(Exception).IsAssignableFrom(exceptionType)) {
                throw new ArgumentException(@"exceptionType must be a type of exception", nameof(exceptionType));
            }
            this.ExceptionType = exceptionType;
            this.Process = handler;
            this.When = when;
        }
    
        public bool IsMatch(Exception error) {
            return this.ExceptionType.IsInstanceOfType(error) && (this.When?.Invoke(error) ?? true);
        }
    }
    

提交回复
热议问题