从C#方法返回不同的类型

THX*_*138 10 c# oop

我有一个方法:

public ??? AuthManager.Login(Credentials credentials)
Run Code Online (Sandbox Code Playgroud)

以下是此方法的一组有效输出值:

  1. 成功(+ accountId)
  2. 失败:AccountLockedOut
  3. 失败:UsernameNotFound
  4. 失败:InvalidPassword(+尝试次数失败)

根据返回类型,向用户显示不同的视图(是的,AccountLockedOut的视图与InvalidPassword不同).

我可以选择:

public class LoginAttemptResult {
    public bool Succeeded { get; set; }
    public AccountId AccountId { get; set; } // for when success
    public LoginAttemptResultEnumType Result { get;set; } // Success, Lockedout, UsernameNotFound, InvalidPassword  
    public int FailedAttemptCount { get; set; } // only used for InvalidPassword
}
Run Code Online (Sandbox Code Playgroud)

我不喜欢这个并寻找更好的解决方案.首先,这导致部分初始化的对象,其中两个违反了接口隔离原则,三个违反了SRP.

更新:抛出异常也不是一个优雅的解决方案,因为InvalidPassword我认为这不是一个例外.数据库连接失败是一个例外.空参数是一个例外.InvalidPassword是一个有效的预期回应.

我认为更好的解决方案是创建类的层次结构:

abstract class LoginAttemptResult
    sealed class LoginSuccess : LoginAttemptResult { AccountId }
    abstract class LoginFailure : LoginAttemptResult
        sealed class InvalidPasswordLoginFailure : LoginFailure { FailedAttemptCount }
        sealed class AccountLockedoutLoginFailure : LoginFailure
Run Code Online (Sandbox Code Playgroud)

Login然后,方法的调用者必须执行以下操作:

if (result is LoginSuccess) { 
    ..."welcome back mr. account id #" + (result as LoginSuccess).AccountId
}
else if (result is InvalidPasswordLoginFailure ) { 
    ..."you failed " + (result as InvalidPasswordLoginFailure).FailedAttemptCount + " times"
}
Run Code Online (Sandbox Code Playgroud)

我没有看到任何错误(概念上)这种方法(除了它附带的许多类).

这种方法还有什么问题?

请注意,这种方法本质上是F#的区分联合(DU).

有没有更好的方法来模拟这个?我已经有几个有效的解决方案 - 现在我想要一个优雅的解决方案.

pol*_*ata 0

你可以返回一个元组

public Tuple<T1,T2> AuthManager.Login(Credentials credentials){
//do your stuff here
return new Tuple<T1,T2>(valueOfT1,valueOfT2);
}
Run Code Online (Sandbox Code Playgroud)