คำตอบง่ายๆคือเมื่อใดก็ตามที่การดำเนินการเป็นไปไม่ได้ (เพราะทั้งแอปพลิเคชันหรือเพราะจะเป็นการละเมิดตรรกะทางธุรกิจ) หากมีการเรียกใช้เมธอดและเป็นไปไม่ได้ที่จะทำตามวิธีที่เขียนขึ้นให้โยนข้อยกเว้น ตัวอย่างที่ดีคือคอนสตรัคเตอร์จะโยน ArgumentExceptions เสมอหากไม่สามารถสร้างอินสแตนซ์ได้โดยใช้พารามิเตอร์ที่ให้มา อีกตัวอย่างหนึ่งคือ InvalidOperationException ซึ่งถูกโยนทิ้งเมื่อไม่สามารถทำการดำเนินการได้เนื่องจากสถานะของสมาชิกรายอื่นหรือสมาชิกของคลาส
ในกรณีของคุณหากมีการเรียกใช้วิธีการเช่นลงชื่อเข้าใช้ (ชื่อผู้ใช้รหัสผ่าน) หากชื่อผู้ใช้ไม่ถูกต้องจะเป็นการโยน UserNameNotValidException หรือ PasswordNotCorrectException หากรหัสผ่านไม่ถูกต้อง ผู้ใช้ไม่สามารถเข้าสู่ระบบโดยใช้พารามิเตอร์ที่ให้มา (เช่นเป็นไปไม่ได้เพราะมันจะละเมิดการรับรองความถูกต้อง) ดังนั้นการโยนข้อยกเว้น แม้ว่าฉันอาจมีข้อยกเว้นสองข้อของคุณสืบทอดมาจาก ArgumentException
ต้องบอกว่าหากคุณไม่ต้องการยกเว้นข้อยกเว้นเนื่องจากความล้มเหลวในการเข้าสู่ระบบอาจเป็นเรื่องธรรมดากลยุทธ์หนึ่งคือการสร้างวิธีที่ส่งกลับประเภทที่แสดงถึงความล้มเหลวที่ต่างกันแทน นี่คือตัวอย่าง:
{ // class
...
public LoginResult Login(string user, string password)
{
if (IsInvalidUser(user))
{
return new UserInvalidLoginResult(user);
}
else if (IsInvalidPassword(user, password))
{
return new PasswordInvalidLoginResult(user, password);
}
else
{
return new SuccessfulLoginResult();
}
}
...
}
public abstract class LoginResult
{
public readonly string Message;
protected LoginResult(string message)
{
this.Message = message;
}
}
public class SuccessfulLoginResult : LoginResult
{
public SucccessfulLogin(string user)
: base(string.Format("Login for user '{0}' was successful.", user))
{ }
}
public class UserInvalidLoginResult : LoginResult
{
public UserInvalidLoginResult(string user)
: base(string.Format("The username '{0}' is invalid.", user))
{ }
}
public class PasswordInvalidLoginResult : LoginResult
{
public PasswordInvalidLoginResult(string password, string user)
: base(string.Format("The password '{0}' for username '{0}' is invalid.", password, user))
{ }
}
นักพัฒนาส่วนใหญ่ได้รับการสอนให้หลีกเลี่ยงข้อยกเว้นเนื่องจากค่าใช้จ่ายที่เกิดจากการขว้างพวกเขา เป็นเรื่องดีที่ต้องคำนึงถึงทรัพยากร แต่โดยปกติแล้วจะไม่ใช่ค่าใช้จ่ายในการออกแบบแอปพลิเคชันของคุณ นั่นอาจเป็นเหตุผลที่คุณถูกบอกไม่ให้ทิ้งข้อยกเว้นสองข้อ ไม่ว่าจะใช้ข้อยกเว้นหรือไม่ปกติจะเดือดลงไปจนถึงความถี่ที่จะเกิดข้อยกเว้น หากเป็นเรื่องธรรมดาหรือเป็นผลลัพธ์ที่คาดหวังได้นี่คือเมื่อนักพัฒนาส่วนใหญ่จะหลีกเลี่ยงข้อยกเว้นและสร้างวิธีการอื่นเพื่อระบุความล้มเหลวแทนเนื่องจากปริมาณการใช้ทรัพยากรที่คาดหมาย
นี่คือตัวอย่างของการหลีกเลี่ยงการใช้ข้อยกเว้นในสถานการณ์เช่นเดียวกับที่อธิบายไว้โดยใช้รูปแบบลอง ():
public class ValidatedLogin
{
public readonly string User;
public readonly string Password;
public ValidatedLogin(string user, string password)
{
if (IsInvalidUser(user))
{
throw new UserInvalidException(user);
}
else if (IsInvalidPassword(user, password))
{
throw new PasswordInvalidException(password);
}
this.User = user;
this.Password = password;
}
public static bool TryCreate(string user, string password, out ValidatedLogin validatedLogin)
{
if (IsInvalidUser(user) ||
IsInvalidPassword(user, password))
{
return false;
}
validatedLogin = new ValidatedLogin(user, password);
return true;
}
}