Как я могу вычесть два универсальных объекта (T - T) в C # (Пример: DateTime - DateTime)? - PullRequest
12 голосов
/ 19 ноября 2011

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

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

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

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

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

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

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

Ответы [ 6 ]

7 голосов
/ 19 ноября 2011

Это невозможно с обобщениями в C # - по крайней мере, не напрямую. Долгое время это была крайне востребованная функция Connect .

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

4 голосов
/ 19 ноября 2011

эта работа

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

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

3 голосов
/ 13 декабря 2013

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

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.

3 голосов
/ 19 ноября 2011

Проверьте «Разное использование» Джона Скита https://jonskeet.uk/csharp/miscutil/

А вот общие операторы Марка Гравелла: https://jonskeet.uk/csharp/miscutil/usage/genericoperators.html

1 голос
/ 19 ноября 2011

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

1 голос
/ 19 ноября 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...