输入通用值(C#)

时间:2008-10-05 20:31:06

标签: c# generics

当我尝试使用泛型类时,this.value为T:

if (this.value.GetType() == typeof(int))
{
    ((int)this.value)++;
}
else
{
    throw new InvalidOperationException
            ("T must be an int to perform this operation");
}

我遇到编译时错误:“无法将类型'T'转换为'int'”

当它是int时,我应该怎么做才能对this.value执行整数运算?

请注意,这只是一个例子。代码使用泛型类型进行转换,“int”只是T的一种类型的示例。

5 个答案:

答案 0 :(得分:24)

不幸的是,很难让编译器相信特定的T实现。一种(讨厌的)方法是在中间转换为对象(注意这将是box和unbox值类型):

int i = (int)(object)this.value;
i++;
this.value = (T)(object)i;

丑陋但它有效。在.NET 3.5中,我有一些更好的通用算术包装器here。 Operator类是MiscUtil的一部分;在最简单的层面上,我怀疑AddAlternative会很好用:

this.value = Operator.AddAlternative(this.value, 1);

这应该推断出隐含的< T,int>自动,或者您可以自己添加:

this.value = Operator.AddAlternative<T,int>(this.value, 1);

好处:这比原始代码更好,因为它实际上并不关心原始T - 它适用于任何支持“T +(T,T)的类型(甚至是你自己的) INT)”。

我认为还有一个隐藏在某处的ChangeType ......

[编辑] Collin K和其他人对建筑意义做了有效的评论 - 但实际上有时候T确实很重要......但是我同意避免这种类型的专业化,除非真的必要。那就是说(根据我对Collin的帖子的评论),能够在(例如)Matrix&lt; T&gt;上执行诸如基本算术(增量,Int32除法等)之类的事情。 [对于十进制的T / float / int / double / etc]通常非常有价值。

答案 1 :(得分:12)

在我看来,泛型类中的特定于类型的代码是代码气味。我会重构它得到这样的东西:

public class MyClass<T>
{
 ...
}

public class IntClass : MyClass<int>
{
  public void IncrementMe()
  {
    this.value++;
  }
}

答案 2 :(得分:3)

C#的静态类型不允许你这样做,但你可以通过强制转换为对象来欺骗它。我不建议这样做,它可能显示架构问题,但无论如何:

using System;

class Foo<T>
{
  public T value;

  public void Increment()
  {
   if (value is int) value = (T)(object)(((int)(object)value)+1);
  }
}

static class Program
{
    static void Main()
    {
     Foo<int> x = new Foo<int>();
     x.Increment();
     x.Increment();
      Console.WriteLine(x.value); 
    }     
}

答案 3 :(得分:0)

我认为我不明白你的意思。如果您要求某些特定类型,那么您可能不应该使用泛型。你可以,这看起来很傻。这将做你要求的,但我不推荐它。

namespace GenericsOne
{
    using System;

class Program
{
    static void Main(string[] args)
    {
        Sample<int> one = new Sample<int>();
        one.AddFive(10);

        // yes, this will fail, it is to show why the approach is generally not a good one.
        Sample<DateTime> two = new Sample<DateTime>();
        two.AddFive(new DateTime());
    }
}

}

namespace GenericsOne
{
    using System;
public class Sample<T>
{
    public int AddFive(T number)
    {
        int junk = 0;

        try
        {
            junk = Convert.ToInt32(number);
        }
        catch (Exception)
        {
            Console.WriteLine("Nope");
        }

        return junk + 5;
    }
}
}

答案 4 :(得分:0)

这就是为什么我真的想要数字或操作约束in C#4

@Marc Gravell的回答是围绕这个问题的最好方法(+1),但是对于泛型问题这是一个令人沮丧的问题。