【问题标题】:How can I subtract two generic objects (T - T) in C# (Example: DateTime - DateTime)?如何在 C# 中减去两个通用对象 (T - T)(示例:DateTime - DateTime)?
【发布时间】:2011-11-18 20:36:02
【问题描述】:

我写了一个泛型类

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

但是当这个属性包含在我的类中时,编译器会在- 运算符上引发逻辑错误

我可以做些什么来正常实现这个目标,还是应该忽略它?

【问题讨论】:

标签: c# generics properties generic-programming


【解决方案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】:

    这对于 C# 中的泛型是不可能的 - 至少不是直接的。 highly requested feature on Connect 很久了。

    你需要让你的类型实现一些接口,该接口有一个可以使用的成员,并将类限制在那个接口上,或者使用 Connect 错误中列出的解决方法之一(都不是完美的),或者像MiscUtil's generic operators 这样的单独方法。

    【讨论】:

      【解决方案3】:

      这个作品

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

      但没有检查,而且很慢

      【讨论】:

        【解决方案4】:

        查看 Jon Skeet 的 Misc Util https://jonskeet.uk/csharp/miscutil/

        这里是 Marc Gravell 的通用运算符:https://jonskeet.uk/csharp/miscutil/usage/genericoperators.html

        【讨论】:

          【解决方案5】:

          编译器这样做是为了避免编写错误代码,这是泛型和类型安全编程概念的全部意义所在。

          如果您需要一种减去日期的方法,请编写一个接受日期的方法,如果您需要另一种用于整数的方法,请猜测您应该为整数编写一个什么方法。泛型不存在,因此编译器可以承担任何类型的责任。想一想,如果我想要两个对象之间的差异,我将如何使用您的泛型方法来做到这一点?

          或者正如@Reed Copsey 提到的,您可以将一个类约束到它。

          【讨论】:

          • 是的,但这不是我的问题,我说为什么不呢?
          • 我给了你一个答案you write a method for int and you write one for date,泛型提供类型安全,而不是它为什么是这样的。
          • 我支持我所说的,愿意接受@RedHat 的反对票。
          • 谢谢乔恩,我先看到你的段落,没有看到第二段,你在编辑答案吗?
          • @RedHat - 我通常从单行开始,然后对其进行扩展。所以是的。
          【解决方案6】:

          虽然这似乎是一个主要限制,但您需要记住 generics 是通用的。当然,System.Int32 类型可以与 C# 的二元运算符一起正常工作。但是,为了论证,如果&lt;T&gt; 是自定义类或结构类型,编译器不能假定它已经重载了+-*/ 运算符。

          【讨论】:

            猜你喜欢
            • 2015-11-19
            • 1970-01-01
            • 1970-01-01
            • 2018-08-02
            • 1970-01-01
            • 2012-04-18
            • 1970-01-01
            • 2011-05-15
            • 1970-01-01
            相关资源
            最近更新 更多