How can I subtract two generic objects (T - T) in C# (Example: DateTime - DateTime)?

喜欢而已 提交于 2019-11-29 07:00:40

问题


I wrote a Generic Class:

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

And I use this class with DateTime, int, etc.

I need a Duration property that returns a duration like:

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

But when this property is included in my class, the compiler raises a logical error on the - operator.

What can I do to achieve this goal normally, or should I ignore it?


回答1:


Try something like this:

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);
    }
}

How this works: first, you convert the arguments to a dynamic type, and you can easily use operators on the dynamic type. If you wouldn't be able to use the operators, then an exception would be thrown at runtime. So, if you try to substract two objects that you actually can't substract, we'll catch the exception and return false as the second item in the Tuple.




回答2:


This is not possible with generics in C# - at least not directly. It has been a highly requested feature on Connect for a long time.

You will need to make your types implement some interface that has a member that can be used, and constrain the class to that, or use one of the workarounds listed in the Connect bug (none of which are perfect), or a separate approach like MiscUtil's generic operators.




回答3:


this work

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

but no check, and slow




回答4:


Check Jon Skeet's Misc Util https://jonskeet.uk/csharp/miscutil/

And here the generic operators by Marc Gravell: https://jonskeet.uk/csharp/miscutil/usage/genericoperators.html




回答5:


The compiler does this so you don't write buggy code, its the whole point of generics and the concept of type safe programming.

If you need a method that subtracts dates write one that accepts a date, and if you need another one for integers, guess what you should write one for integers. Generics are not there so that the compiler can assume responsibility for any type. Think about it what if I wanted the difference between two objects, how would I do that with your generic method?

Or as @Reed Copsey mentioned you can constrain a class to it.




回答6:


While this may seem like a major restriction, you need to remember that generics are generic. Of course, the System.Int32 type can work just fine with the binary operators of C#. However, for the sake of argument, if <T> were a custom class or structure type, the compiler cannot assume it has overloaded the +, -, *, and / operators.



来源:https://stackoverflow.com/questions/8188784/how-can-i-subtract-two-generic-objects-t-t-in-c-sharp-example-datetime-d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!