Подтвердить что ты не робот

Как я могу вычесть два общих объекта (T - T) в С# (например: DateTime - DateTime)?

Я написал Общий класс:

public class Interval<T> where T : IComparable // for checking that Start < End 
{
    public T Start { get; set; }
    public T End { get; set; }
    ...
}

И я использую этот класс с DateTime, int и т.д.

Мне нужно свойство Длительность, которое возвращает продолжительность, например:

public object Duration
{
    get
    {
        return End - Start;
    }
}

Но когда это свойство включено в мой класс, компилятор вызывает логическую ошибку для оператора -.

Что я могу сделать для достижения этой цели, или я должен игнорировать?

4b9b3361

Ответ 1

Попробуйте что-то вроде этого:

static void Main(string[] args)
{
    Tuple<int, bool> value = JustAMethod<int>(5, 3);
    if (value.Item2)
    {
        Console.WriteLine(value.Item1);
    }
    else
    {
        Console.WriteLine("Can't substract.");
    }
}
public static Tuple<T, bool> JustAMethod<T>(T arg1, T arg2)
{
    dynamic dArg1 = (dynamic)arg1;
    dynamic dArg2 = (dynamic)arg2;
    dynamic ret;
    try
    {
        ret = dArg1 - dArg2;
        return new Tuple<T, bool>(ret, true);
    }
    catch
    {
        return new Tuple<T, bool>(default(T), false);
    }
}

Как это работает: во-первых, вы преобразовываете аргументы в динамический тип, и вы можете легко использовать операторы в динамическом типе. Если вы не сможете использовать операторы, тогда исключение будет выбрано во время выполнения. Итак, если вы попытаетесь вычесть два объекта, которые вы фактически не можете вычесть, мы поймаем исключение и вернем false в качестве второго элемента в Tuple.

Ответ 2

Это невозможно с использованием дженериков в С# - по крайней мере, не напрямую. Это долгое время запрошенная функция в Connect.

Вам нужно будет сделать ваши типы реализованы с помощью какого-либо интерфейса, в котором есть член, который может использоваться, и ограничивать его классом или использовать одно из обходных решений, перечисленных в ошибке Connect (ни одна из которых не является идеальной), или отдельный подход, например общие операторы MiscUtil.

Ответ 3

эта работа

public object Duration
{
    get
    {
        return (dynamic)End - (dynamic)Start;
    }
}

но без проверки и медленного

Ответ 5

Компилятор делает это, поэтому вы не пишете багги-код, его точку генерации и концепцию безопасного программирования типов.

Если вам нужен метод, который вычитает даты, пишется тот, который принимает дату, а если вам нужен другой для целых чисел, угадайте, что вы должны написать для целых чисел. Генералов нет, поэтому компилятор может взять на себя ответственность за любой тип. Подумайте об этом, если бы я хотел разницу между двумя объектами, как бы я сделал это с помощью вашего общего метода?

Или, как упоминал @Reed Copsey, вы можете ограничить его классом.

Ответ 6

В то время как это может показаться серьезным ограничением, вам нужно помнить, что генерики являются общими. Конечно, тип System.Int32 может отлично работать с бинарными операторами С#. Однако, для аргумента, если <T> был пользовательским типом класса или структуры, компилятор не может предположить, что он перегрузил операторы +, -, * и /.