我正在尝试写出具有附加功能的泛型类的特定情况,但我不确定为什么会发生以下情况。
假设我有一个泛型类:
class Generic<T>
{
protected T value;
}
如果我写出一个特定的实现,我实际上无法使用我将其缩小到的特定类型:
编辑:我搞砸了,这不起作用。class Generic<float>
{
// This doesn't work
public void Add()
{
value + 1.0f;
}
}
但如果我从特定版本继承,它确实有效:
class Specific : Generic<float>
{
// This does work
public void Add()
{
value + 1.0f;
}
}
答案 0 :(得分:4)
如果有人还在读这篇文章,我想指出这似乎可以通过扩展方法实现:
class Generic<T>
{
public T value;
}
static class Extension
{
public static void Add (this Generic<float> generic)
{
generic.value += 1.0f;
}
}
缺点似乎是&#39;价值&#39;必须是公开的或内部的。
答案 1 :(得分:0)
您的第一次尝试根本不是有效声明 - 指定类的部分不能指定任何类型参数。
如果您考虑一下,CLR将如何知道是否有可用的专用类型?如果在两个加载的程序集中存在两个相同泛型类型的不同特化,它会怎么做?每当第一次使用特定类型的参数组合时,它必须检查所有引用的程序集。 (这不能在编译时完成,因为其他类可能只是指Generic<T>
。)
在许多情况下,可以使用类型的值,这些方式对使用约束的类型有意义。例如,如果您使用T
约束where T : IComparable<T>
,则可以使用T
比较任意两个Compare
值。遗憾的是,虽然您可能希望查看Marc Gravell's generic operator work in MiscUtil,但无法以这种方式表示算术运算符。
虽然我感觉到你的痛苦,但在.NET泛型中却没有这样的东西 - 你会想到你正在努力解决的任何问题的替代设计。
答案 2 :(得分:0)
在这种情况下:
class Generic<float>
{
// This doesn't work
public void Add()
{
value + 1.0f;
}
}
这并不意味着您使用float作为泛型类型使用Generic类,但这意味着泛型类型的名称在源代码中是“float”(而不是使用T,您使用的是“float”因此,它没有转换为float。换句话说,你使用通用符号作为模板,以后可以用真实类型替换(但不是在模板本身,这就是为什么在C ++中它们被称为模板)
在此代码中:
class Specific : Generic<float>
{
// This does work
public void Add()
{
value + 1.0f;
}
}
你告诉编译器你希望特定的类是泛型类的子类,而它的模板类型将被float类型替换。
答案 3 :(得分:0)
通用类型用于算术可重用性。也就是说,你必须在代码中的所有可能的Ts之间写一些共同点。
class Generic<T>
{
protected T value; //it's valid to declare a member whose type is T
public void Add()
{
value + 1.0f; //invalid, because not all T are allowed to add
//with 0.1f by default
//consider T is the type Person
}
public void Print()
{
Type t = typeof(T); //valid, for all T we can get its type
}
}
当你指定一些T(例如你的问题浮点数)时,编译器知道T是浮点数,所以向它添加0.1f是有效的。
答案 4 :(得分:0)
我也寻找类似的解决方案,我想你也从ADA或这样的编程语言中得到了这个想法。 但是,正如其他人所写,使类型特定的类定义不是泛型编程,它是专业化的,所以最简单的(并且只有在C#中)方法是基于通用结构创建指定的类:
class Generic<T>
{
protected T value;
public Generic(T val)
{
value = val;
}
}
class Generic_float : Generic<float>
{
public Generic_float(float val)
: base(val)
{
}
public void Add()
{
value = value + 1.0f;
}
}
如您所见,我们为指定的案例创建了一个类,具有使用字段和方法扩展结构的额外功能。这个优点非常适合细化我们对象的行为,并且能够将类型化泛型类隐式强制转换为我们自定义的类(注意不能返回):
public void Test()
{
Generic<float> var1 = new Generic<float>(1.5f);
Generic_float var2 = new Generic_float(2.5f);
var1 = var2; // Works, var links to var2's memory field casted as Generic<float>
var2 = var1; // cannot implicitly convert error, if want to use then have to make explicit conversion
}
不知道您的预期方式是否应该使用C#或其他托管语言等语言,但也许这种解决方法可以为您提供您真正想要的内容。