Получить экземпляр общего типа

У меня есть 2 класса клиентов BusinessCustomer и NormalCustomer, имеющие индивидуальные свойства и метод проверки. Из класса реализации, основываясь на некоторых условиях, я могу создать Customer1 или Customer2. Как создать экземпляр BusinessCustomer или NormalCustomer на основе T в классе Customer, чтобы я мог вызвать метод проверки, общий для обоих классов.

public class Customer<t> where T : class
 {
 public T CustomerType;
 bool isValid;

 public Customer() //constructor
 {
 //for customer1, i want a new instance of BusinessCustomer 
 //for customer2, i want a new instance of NormalCustomer 
 }

 public bool Validate()
 {
 isValid = CustomerType.Validate();
 }
 }


public class BusinessCustomer
{
 public string CustomerHobby { get; set; }
 public bool Validate()
 {
 return true;
 }
}

public class NormalCustomer
{
 public string CustomerEducation { get; set; }
 public bool Validate()
 {
 return false;
 }
}

public class Implement
{
 public void ImplementCustomer()
 {
 var customer1 = new Customer<businesscustomer>();
 customer1.CustomerType = new BusinessCustomer {CustomerHobby="Singing"};
 customer1.Validate();

 var customer2 = new Customer<normalcustomer>();
 customer2.CustomerType = new NormalCustomer { CustomerEducation = "High School" };
 customer2.Validate();

 }
}
</normalcustomer></businesscustomer></t>
1 ответ

Ваша первая проблема связана со следующей строкой:

isValid = CustomerType.Validate();

Поскольку CustomerType имеет тип T, который может быть любым классом, компилятор не может гарантировать, что будет вызван метод Validate(). Вы должны исправить это, создав общий интерфейс. Позвольте назвать этот ICustomer:

interface ICustomer
{
 bool Validate();
}

Теперь, как BusinessCustomer и NormalCustomer, потребуется реализовать указанный интерфейс:

public class BusinessCustomer : ICustomer
{
 // Same code
}

public class NormalCustomer : ICustomer
{
 // Same code
}

Затем вам нужно будет изменить:

public class Customer<t> where T : class
</t>

Для того, чтобы:

public class Customer<t> where T : ICustomer
</t>

Теперь вы сможете создавать экземпляры Customer где T реализует ICustomer, что позволит вам вызвать метод Validate CustomerType.

Затем, если вы хотите обновить T в своем конструкторе, вы можете сделать так:

public Customer()
{
 CustomerType = new T();
}

Но ждать. Что делать, если T не имеет общедоступного конструктора по умолчанию или является абстрактным? Нам также необходимо добавить это ограничение в наш общий тип:

public class Customer<t> where T : class, new()
</t>

Теперь new T(); работает, и вы можете создавать экземпляры Customer где T имеет конструктор по умолчанию. Вам больше не придется устанавливать customer1.CustomerType если вы этого не хотите.

Еще одно замечание. Ваш метод:

public bool Validate()
{
 isValid = CustomerType.Validate();
}

Либо нужно вернуть bool (например, isValid), либо подпись должна быть void Validate(). Прямо сейчас вы получите ошибку компилятора, потому что не все пути кода возвращают значение.

Надеюсь это поможет!

licensed under cc by-sa 3.0 with attribution.