为什么在c#异常类中没有带有1个异常参数的构造函数?

时间:2015-10-27 21:50:17

标签: c# exception

System.Exception类有4个构造函数:

public Exception();
public Exception(string message);
protected Exception(SerializationInfo info, StreamingContext context);
public Exception(string message, Exception innerException);

为什么它没有这个构造函数?

public Exception(Exception innerException);


这是一个有用的地方。

我有一个静态方法来获得开放连接:

public static DbConnection GetOpenConnection(string dataProvider, string connectionString) 
{
   DbConnection dbConnection = GetDbProviderFactory(dataProvider).CreateConnection();
   dbConnection.ConnectionString = connectionString;
   dbConnection.Open();
   return dbConnection;
}

如果发生任何错误,我希望此方法抛出自定义异常GetOpenConnectionException

所以我创建了自定义异常GetOpenConnectionException

public class GetOpenConnectionException : Exception
{
   public GetOpenConnectionException(string message) : base(message)
   {
   }
   public GetOpenConnectionException(string message, Exception innerException) : base(message, innerException)
   {
   }
}

由于Exception没有构造函数public Exception(Exception innerException),我无法在GetOpenConnectionException中使用此代码:

public GetOpenConnectionException(Exception innerException) : base(innerException)
{
}

所以我被迫以这种方式编写GetOpenConnection()方法:

public static DbConnection GetOpenConnection(string dataProvider, string connectionString) 
{
   try 
   {
      DbConnection dbConnection = GetDbProviderFactory(dataProvider).CreateConnection();
      dbConnection.ConnectionString = connectionString;
      dbConnection.Open();
      return dbConnection;
   }
   catch (Exception e)
   {
      throw new GetOpenConnectionException("", e);
   }
}

我想要的是以这种方式编写GetOpenConnection()方法:

public static DbConnection GetOpenConnection(string dataProvider, string connectionString) 
{
   try 
   {
      DbConnection dbConnection = GetDbProviderFactory(dataProvider).CreateConnection();
      dbConnection.ConnectionString = connectionString;
      dbConnection.Open();
      return dbConnection;
   }
   catch (Exception e)
   {
      throw new GetOpenConnectionException(e);
   }
}

这有意义吗?

3 个答案:

答案 0 :(得分:4)

   public GetOpenConnectionException(Exception innerException) : base("", innerException)
   {
   }

答案 1 :(得分:1)

其他答案提供了很好的方法来实现您的要求,但我相信您的问题的核心是:“为什么这首不存在?”

当例程关于它使用的资源的假设或先决条件及其请求的参数未得到满足时,通常会抛出异常。抛出的异常应该有助于调用者(或程序员)理解未满足的假设或先决条件,以便他们可以相应地处理它或修复他们的代码。该消息是该通信的关键部分。我甚至会猜测,如果Exception类不需要序列化,那么甚至不会有一个空的构造函数!

将异常嵌套在另一个异常中意味着嵌套异常是容器异常的原因。 (Exception类的特定构造函数的documentation指向这一点。)如果您只是传递一个内部异常而没有任何消息,那么这实际上会转换为“我将抛出一个不提供其他信息的异常超越它的类型。“这不是很有帮助,简单地抛出原始异常可能会更好。

这是您提供更有意义的消息的一种方式:

public static DbConnection GetOpenConnection(string dataProvider, string connectionString) 
{
   try 
   {
      DbConnection dbConnection = GetDbProviderFactory(dataProvider).CreateConnection();
      dbConnection.ConnectionString = connectionString;
      dbConnection.Open();
      return dbConnection;
   }
   catch (Exception e) // consider changing this to a more specific type of exception, as an error with .Open() is not the only way it could fail
   {
      // provide a meaningful message to the caller about the context of this error
      var message = string.Format("An error occurred while trying to connect to the data provider {0} with the connection string {1}.", dataProvder, connectionString);
      throw new GetOpenConnectionException(message, e);
   }
}

答案 2 :(得分:0)

与Piotr Dory的答案类似,你可以这样做:

$stateProvider
        .state('login', {
            url: '/login',
            templateUrl: 'login/login.html',
            controller: 'LoginCtrl',
            authenticate: false
        })
        .state('dashboard', {
            url: '/dashboard',

            views: {
                '': {
                    templateUrl: 'dashboard/dashboard.html',
                    controller: 'DashboardCtrl'
                },
                'current-status-module@dashboard': {
                    templateUrl: 'current-status/current-status.html'
                },
                'alerts-module@dashboard': {
                    templateUrl: 'alerts/alerts.html',
                    controller: 'AlertCardsCtrl',
                    resolve: {
                        ZonesService: 'ZonesService',
                        userZones: function (LoginService, ZonesService, $stateParams) {
                            return ZonesService.query({zoneId: $stateParams.zoneId}).then(function(data){
                                return data;
                            });
                        }
                    }
                },
                'alert-cards-module@dashboard': {
                    templateUrl: 'alerts/alert-cards/alert-cards.html'
                },
                'zones-module@dashboard': {
                    templateUrl: 'zones/zones.html'
                },
                'map-grid-module@dashboard': {
                    templateUrl: 'zones/zone-map/zone-map.html'
                }
            },
            authenticate: true
        })




.factory('LoginService', function ($window, $http, $q, $state, ENV) {
    return {
        login: function (username, password) {
            var deferred = $q.defer();
            $http.post(ENV.web_api_url + ENV.api_version + '/login', {}, {
                "headers": {
                    "X-Auth-Username": username,
                    "X-Auth-Password": password
                }
            }).success(function (data) {
                $window.sessionStorage.token = data.token;
                deferred.resolve(data);
                $state.transitionTo("dashboard");
            }).error(function (error) {
                deferred.reject(error);
            });
            return deferred.promise;
        },
        isAuthenticated: function () {
            //==TODO: Call endpoint to check auth token
            return true;
        },
        isRestricted: function () {
            return ENV.is_restricted;
        },
        logout: function (error) {
            // User isn’t authenticated
            $window.sessionStorage.notification = "Authenticated session has expired. Please log in again.";
            $window.sessionStorage.notifyAlert = 'show';
            $window.location = ENV.location_path_home;
        }
    }
});


.run(function ($window, $rootScope, $state, LoginService) {
    $rootScope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams) {
        $rootScope.user = angular.fromJson($window.sessionStorage.user);
        $rootScope.loggedIn = $window.sessionStorage.loggedIn;

        if (toState.authenticate && !LoginService.isAuthenticated()) {
            // User isn’t authenticated
            $state.transitionTo("login");
            event.preventDefault();
        }

        if (toState.restricted && LoginService.isRestricted()) {
            console.log("restricted...")
            // Action is restricted to user
            $rootScope.selectedIndex = 0;
            event.preventDefault();
        }
    });
});

这样你就可以将有意义的东西传递给基础构造函数。

至于为什么没有一个构造函数只接受一个Exception参数......它似乎并没有真正的理由。他们很容易就可以拥有。