1. ホーム
  2. c#

switch文において指定されたケースが処理できない場合に例外を発生させる方法

2023-10-29 22:05:43

質問

MVCアプリのシステムで、あるユーザーのパスワードを変更する関数があるとします。

public JsonResult ChangePassword
    (string username, string currentPassword, string newPassword)
{
    switch (this.membershipService.ValidateLogin(username, currentPassword))
    {
        case UserValidationResult.BasUsername:
        case UserValidationResult.BadPassword:
            // abort: return JsonResult with localized error message        
            // for invalid username/pass combo.
        case UserValidationResult.TrialExpired
            // abort: return JsonResult with localized error message
            // that user cannot login because their trial period has expired
        case UserValidationResult.Success:
            break;
    }

    // NOW change password now that user is validated
}

membershipService.ValidateLogin()UserValidationResult と定義された enum を返します。

enum UserValidationResult
{
    BadUsername,
    BadPassword,
    TrialExpired,
    Success
}

守備範囲の広いプログラマである私なら、上記の ChangePassword() メソッドを変更して、認識されない UserValidationResult から戻ってきた値が ValidateLogin() :

public JsonResult ChangePassword
    (string username, string currentPassword, string newPassword)
{
    switch (this.membershipService.ValidateLogin(username, currentPassword))
    {
        case UserValidationResult.BasUsername:
        case UserValidationResult.BadPassword:
            // abort: return JsonResult with localized error message        
            // for invalid username/pass combo.
        case UserValidationResult.TrialExpired
            // abort: return JsonResult with localized error message
            // that user cannot login because their trial period has expired
        case UserValidationResult.Success:
            break;
        default:
            throw new NotImplementedException
                ("Unrecognized UserValidationResult value.");
            // or NotSupportedException()
            break;
    }

    // Change password now that user is validated
}

私はいつも、上記の最後のスニペットのようなパターンをベストプラクティスだと考えています。たとえば、ある開発者が、ユーザーがログインしようとしたときに、これこれのビジネス上の理由がある場合は、まずビジネスに連絡するようにという要件を得たとしたらどうでしょうか。そこで UserValidationResult の定義が更新され、次のようになります。

enum UserValidationResult
{
    BadUsername,
    BadPassword,
    TrialExpired,
    ContactUs,
    Success
}

開発者は ValidateLogin() メソッドを変更して、新しい列挙型の値を返すようにします ( UserValidationResult.ContactUs ) を返しますが ChangePassword() . スイッチに例外がなければ、そもそもログインの試みが検証されるべきでないのに、ユーザーはまだパスワードを変更することが許されているのです!

私だけでしょうか、それともこの default: throw new Exception() は良いアイデアだと思いますか?私は何年か前にそれを見て、いつも(それを理解した後)それがベストプラクティスであると仮定しています。

どのように解決するのですか?

この場合、私はいつも例外を投げています。そこで InvalidEnumArgumentException を使うことを検討してください。