我试图用C#编写可与不同维度的几何实体一起使用的通用算法。
在以下人为设计的示例中,我Point2
和和Point3
都实现了一个简单的IPoint
接口。
现在,我有一个GenericAlgorithm
调用函数的函数GetDim
。根据类型,此函数有多个定义。还为所有实现的东西定义了一个后备功能IPoint
。
我最初希望以下程序的输出为2、3。但是,它的值为0、0。
interface IPoint {
public int NumDims { get; }
}
public struct Point2 : IPoint {
public int NumDims => 2;
}
public struct Point3 : IPoint {
public int NumDims => 3;
}
class Program
{
static int GetDim<T>(T point) where T: IPoint => 0;
static int GetDim(Point2 point) => point.NumDims;
static int GetDim(Point3 point) => point.NumDims;
static int GenericAlgorithm<T>(T point) where T : IPoint => GetDim(point);
static void Main(string[] args)
{
Point2 p2;
Point3 p3;
int d1 = GenericAlgorithm(p2);
int d2 = GenericAlgorithm(p3);
Console.WriteLine("{0:d}", d1); // returns 0 !!
Console.WriteLine("{0:d}", d2); // returns 0 !!
}
}
好的,因此由于某种原因,具体类型信息丢失了GenericAlgorithm
。我不完全理解为什么会这样,但是很好。如果我不能这样做,我还有什么其他选择?
因此,基本上可以编译。最初,我认为如果JIT编译器在运行时找不到专用的实现
—
mohamedmoussa
GetDim
(即,我通过a Point4
但GetDim<Point4>
不存在),则需要回退功能。但是,似乎编译器不会费心寻找专门的实现。
@woggy:您说“似乎没有编译器会去寻找专门的实现”,就好像设计师和实现者的懒惰一样。不是。这是.NET中泛型的表示方式的问题。它只是与C ++中的模板不同。泛型方法不会针对每个类型参数单独编译-只会编译一次。当然,这有优点也有缺点,但这不是“生硬”的问题。
—
乔恩·斯基特
@jonskeet抱歉,如果我的语言选择不佳,我敢肯定这里没有考虑到复杂性。我的理解是,编译器不会为引用类型编译单独的函数,而是为值类型/结构编译,是正确的吗?
—
mohamedmoussa
@woggy:那是JIT编译器,它与C#编译器是完全独立的事情-它是执行重载解析的C#编译器。通用方法的IL仅生成一次-每个专门化不会生成一次。
—
Jon Skeet
NumDims
属性可用。为什么在某些情况下会忽略它?