当我尝试使用泛型类时,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的一种类型的示例。
答案 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),但是对于泛型问题这是一个令人沮丧的问题。