オブジェクトの初期化を中止するには、コンストラクターで例外をスローします。無効な入力を拒否することをお勧めします。
public class User
{
public User(String name) {
if (String.IsNullOrWhiteSpace(name)) {
if (name == null) {
throw new System.ArgumentNullException("Cannot be null.", "name");
}
else {
throw new System.ArgumentException("Cannot be empty.", "name");
}
}
}
}
コンストラクターで定義したいビジネスロジックがそこに適合しません。コンストラクターは軽量で、インスタンス化のみである必要があります。一部のデータソースのクエリは、コンストラクターにとってコストがかかりすぎます。このため、代わりにファクトリパターンを使用する必要があります。ファクトリパターンを使用すると、呼び出し元は、オブジェクトの作成に伴う手間のかかる作業が発生することを期待する場合があります。
public class User
{
private User(String name) {
if (String.IsNullOrWhiteSpace(name)) {
if (name == null) {
throw new System.ArgumentNullException("Cannot be null.", "name");
}
else {
throw new System.ArgumentException("Cannot be empty.", "name");
}
}
}
public static User CreateUser(String name) {
User user = new User(name); // Lightweight instantiation, basic validation
var matches = allUsers.Where(q => q.Name == name).ToList();
if(matches.Any())
{
throw new System.ArgumentException("User with the specified name already exists.", "name");
}
Name = name;
}
public String Name {
get;
private set; // Optionally public if needed
}
}
ファクトリパターンの方が適していることがわかります。これはメソッドであるため、呼び出し元は、ファクトリパターンを呼び出すことで何らかの作業が行われていることを期待できます。一方、コンストラクターを使用すると、軽量であることが期待されます。
コンストラクタールートを使用する場合は、データソースへの実際の挿入が試行されるときなど、ビジネスルールを適用する他の方法を試してください。
public class User
{
public User(String name) {
if (String.IsNullOrWhiteSpace(name)) {
if (name == null) {
throw new System.ArgumentNullException("Cannot be null.", "name");
}
else {
throw new System.ArgumentException("Cannot be empty.", "name");
}
}
}
}
public class SomeDataSource {
public void AddUser(User user) {
// Do your business validation here, and either throw or possibly return a value
// If business rules pass, then add the user
Users.Add(user);
}
}