Доброго времени суток.
Есть Класс.
/// <summary>
/// Класс, являющийся "Номер Телефона".
/// </summary>
/// <typeparam name="T">Тип, в котором хранится Тип Номера Телефона.</typeparam>
// Кстати string не может быть ограничителем.
public class TelNumber<T> where T : string
{
/// <summary>
/// ID Номер Телефона.
/// </summary>
public int TelNumberID { get; set; }
/// <summary>
/// Тип Номер Телефона.
/// </summary>
public TypeTelNumber<int,T> TypeTelNumber { get; set; }
}
Я хочу, чтобы тип телефона мог быть мог быть либо string, либо TypeTelNumber<I,T>.
Пишу так:
/// <summary>
/// Класс, являющийся "Номер Телефона".
/// </summary>
/// <typeparam name="T">Тип, в котором хранится Тип Номера Телефона.</typeparam>
public class TelNumber<T> where T : string, TypeTelNumber<I,T>
{
/// <summary>
/// ID Номер Телефона.
/// </summary>
public int TelNumberID { get; set; }
/// <summary>
/// Тип Номер Телефона.
/// </summary>
public T TypeTelNumber { get; set; }
}
Вопрос: Ругается на I, мол не такого типа (понятно и логично). Но как тогда сделать задуманное?
Ваш код where T : string означает, что Т может быть только string, поскольку класс System.String объявлен как sealed.
Чтобы скомпилировалось, достаточно объявить параметр I:
public class TelNumber<I, T> where T : string, TypeTelNumber<I,T>
{
/// <summary>
/// ID Номер Телефона.
/// </summary>
public int TelNumberID { get; set; }
/// <summary>
/// Тип Номер Телефона.
/// </summary>
public T TypeTelNumber { get; set; }
}
Но это не то, что вам нужно: в C# нет discriminated union-типов. Код where T : string, TypeTelNumber<I,T> означает, что T должен быть одновременно и string, и TypeTelNumber<I,T>. А поскольку string есть sealed, это означает, что ваш код не скомпилируется ни с каким типом.
Имеет смысл объявить просто два отдельных класса, реализующих общий интерфейс.
interface class ITelNumber<T>
{
/// <summary>
/// ID Номер Телефона.
/// </summary>
int TelNumberID { get; set; }
/// <summary>
/// Тип Номер Телефона.
/// </summary>
T TypeTelNumber { get; set; }
}
class StringTelNumber : ITelNumber<string>
{
public int TelNumberID { get; set; }
public string TypeTelNumber { get; set; }
}
class CustomTelNumber<I, T> : ITelNumber<TypeTelNumber<I, T>>
{
public int TelNumberID { get; set; }
public TypeTelNumber<I, T> TypeTelNumber { get; set; }
}
А ограничения на типы налагать уже вашей бизнес-логикой, а не системой типов: в C# система типов такого (пока) не умеет.
Как ответили в комментариях, пока задуманного сделать нельзя, ибо мой первый кусок означает И, а не ИЛИ.
Сделать, как в моем варианте.
Не ставить ограничений, т.е
/// <summary>
/// Класс, являющийся "Номер Телефона".
/// </summary>
/// <typeparam name="T">Тип, в котором хранится Тип Номера Телефона.</typeparam>
public class TelNumber<T>
{
/// <summary>
/// ID Номер Телефона.
/// </summary>
public int TelNumberID { get; set; }
/// <summary>
/// Тип Номер Телефона.
/// </summary>
public T TypeTelNumber { get; set; }
}
Во втором варианте появляется проблема, что я не могу контролировать какой тип используется для хранения типа. Ну и ладно((
Сделать так, как предложил VladD в ответе. Именно это вариант я и использую.
Продвижение своими сайтами как стратегия роста и независимости