代码之家  ›  专栏  ›  技术社区  ›  JL. Hans Passant

C是否可以有一个通用返回类型?

c#
  •  5
  • JL. Hans Passant  · 技术社区  · 15 年前

    这里是一个典型的函数,它返回真/假;

    private static bool hasValue()
    {
        return true; 
    }
    

    现在,如果出现错误,我将返回我自己的自定义错误对象和定义:

    public class Failure
        {
            public string FailureDateTime { get; set; }
            public string FailureReason { get; set; }
        }
    

    我希望能够抛出这个自定义对象,例如…

    private static bool hasValue()
    {
        try
            {
               ...do something
            }
        catch 
            {
             throw new Failure();
             }
        return true; 
    }
    

    这是不可能的,我不想从System.IO.Exception派生失败,因为我个人在C中序列化异常时遇到了问题(这是在.NET v2中)。

    这个问题的最佳实践/或理想解决方案是什么?我应该只使用私有静态对象吗?或者是否有更清晰的方法返回自定义对象或在出现错误时绕过典型的返回类型(不使用System.IO.Exception)?

    我也不太喜欢使用对象,因为我需要使用强制转换和更多布尔值来验证结果。

    7 回复  |  直到 15 年前
        1
  •  10
  •   Elisha    15 年前

    这种解决方案可能适合这种情况:

    var exception = new Exception();
    exception.Data.Add("Failure", new Failure());
    throw exception;
    

    您可以抛出异常(建议定义自己的异常类型),并使用数据字典来保存失败。在 catch 代码可以获取数据并将其序列化。如果确实创建了自己的异常类型,则可以将失败放在属性上。

    注释:我没有检查它,但是您确定异常是不可序列化的吗?

        2
  •  7
  •   Mark Byers    15 年前

    我不想从System.IO.Exception派生失败,因为无法在C中序列化异常。

    这个问题所基于的假设是,您不能序列化派生自 IOException . 然而,我想挑战这个假设。 异常 标记为 Serializable . 您所要做的就是将子类也标记为可序列化。

    参见文档 IOException :

    [SerializableAttribute]
    [ComVisibleAttribute(true)]
    public class IOException : SystemException
    
        3
  •  6
  •   Igor Zevaka    15 年前

    你需要从 System.Exception (或任何其他非- sealed 子类)。您所说的序列化失败可能是因为您没有实现序列化构造函数。

    Visual Studio有一个代码段,用于为子类化异常创建推荐的模板。你可以通过打字得到它 exception 压榨 标签 两次。

    这就是结果:

    [Serializable]
    public class MyException : Exception {
        public MyException() { }
        public MyException(string message) : base(message) { }
        public MyException(string message, Exception inner) : base(message, inner) { }
        protected MyException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }
    }
    
        4
  •  1
  •   Flatlineato    15 年前

    从异常中获取并使对象可序列化

        5
  •  0
  •   Will    15 年前

    不要太担心这种情况;只需创建一个结果类型来封装所有这些逻辑。

    public class ValueResult
    {
      public Failure FailureDetails {get;set;}
      public bool Success {get;set;}
      public bool HasValue {get;set;}
      public object Value {get;set;}
    }
    

    var result = HasValue();
    if(result.Success)
      DoSomething(result.Value);
    else if(!result.Success)
      LogFailure(result.FailureDetails);
    
        6
  •  0
  •   Michael D. Irizarry    15 年前

    此外,您还可以对自定义异常始终使用企业库异常处理,为异常处理、格式化类型、日志记录等提供您自己的类。

    try
    {
    }
    catch(Exception ex)
    {
        bool rethrow = ExceptionPolicy.HandleException(ex, "My Custom Policy");
        if (rethrow)
        {
            throw;
        }
    }
    finally
    {
    }
    

    实例:

    http://weblogs.asp.net/sukumarraju/archive/2009/10/04/microsoft-enterprise-library-4-1-exception-handling-block.aspx

    http://www.imason.com/imason_Blogs/b/suleman_ibrahim/archive/2009/05/25/configuring-enterprise-library-4-0-for-exception-handling-and-logging.aspx

        7
  •  0
  •   Spyros    15 年前

    您必须创建这样一个从异常继承的类:

    [Serializable]
    public class Failure: Exception
    {
        public string ErrorMessage
        {
          get
           {
             return base.Message.ToString();
           }
        }
    
    }
    

    然后

    catch(Exception ex)
    {
        throw new Failure(
              "exception message here", ex.messege);
    }