我正在尝试用 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 !!
}
}
Run Code Online (Sandbox Code Playgroud)
好的,由于某种原因,具体的类型信息在GenericAlgorithm. 我不完全理解为什么会发生这种情况,但很好。如果我不能这样做,我还有什么其他选择?
Jon*_*eet 10
这种方法:
static int GenericAlgorithm<T>(T point) where T : IPoint => GetDim(point);
Run Code Online (Sandbox Code Playgroud)
... 会一直打电话GetDim<T>(T point)。重载决议在编译时执行,在那个阶段没有其他适用的方法。
如果您希望在执行时调用重载解析,则需要使用动态类型,例如
static int GenericAlgorithm<T>(T point) where T : IPoint => GetDim((dynamic) point);
Run Code Online (Sandbox Code Playgroud)
但是,为此使用继承通常是一个更好的主意-在您的示例中,显然您可以只使用单个方法并返回point.NumDims。我假设在你的真实代码中,有一些原因是等价的更棘手,但如果没有更多的上下文,我们无法就如何使用继承来执行专业化提出建议。这些是你的选择:
从 C# 8.0 开始,您应该能够为您的接口提供默认实现,而不是需要泛型方法。
interface IPoint {
int NumDims { get => 0; }
}
Run Code Online (Sandbox Code Playgroud)
实现通用方法和每个IPoint实现的重载也违反了 Liskov 替换原则(SOLID 中的 L)。您最好将算法推送到每个IPoint实现中,这意味着您应该只需要一个方法调用:
static int GetDim(IPoint point) => point.NumDims;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
330 次 |
| 最近记录: |