C#泛型 - 模仿C ++模板专业化

时间:2011-10-05 17:43:37

标签: c# generics

我在C ++ Tenmplates上找到了一个很好的链接:

http://www.cplusplus.com/doc/tutorial/templates/

并且在C#中需要类似的东西。我有一个似乎有效的解决方案,但希望其他人知道如何与上述链接相关,特别是专业化部分。

以下是我提出的概念证明:

public abstract class Piece
{
    public object Value { get; set; }
}

public class Rook : Piece
{
    public void Capture()
    {
        int i = (int)this.Value;
    }
}

public class Pawn : Piece
{
    public void CaptureEnPassant()
    {
        string s = (string)this.Value;
    }
}

public class PieceFactory<P, T> where P : Piece, new()
{

    P p;

    public PieceFactory(T value)
    {
        p = new P();
        p.Value = value;
    }

    public P GetPiece()
    {
        return p;
    }
}

然后最后打电话到工厂我这样做:

var piece = new PieceFactory<Pawn, string>("exd6").GetPiece();

piece.CaptureEnPassant();

我见过不同的解决方案,比如使用扩展方法和其他方式......

只是想看看我的思维方式是否符合良好的模式。

非常感谢,

大卫

3 个答案:

答案 0 :(得分:8)

我的观点是你的草图比必要的要复杂得多,令人困惑。为什么基类具有在每个派生类中具有不同含义和不同类型的“值”?为什么有一个工厂采用必须属于特定类型参数的类型参数,如果不是,那么程序在运行时崩溃 ?摆脱所有脆弱,混乱,脆弱的东西。如果一个pawn需要一个字符串,那么在Pawn上创建一个带有字符串的公共构造函数,故事结束。这里根本不需要工厂模式。

不要那么喜欢你用它构建东西的工具,这实际上没有任何意义。通用类型非常适合集合类之类的东西。它们不适合国际象棋领域。

答案 1 :(得分:1)

仅供参考我尝试将我自己的模板编程的国际象棋引擎转换为C#以获得乐趣,并且发现它的速度大约相当于20 [] [原文如此]。

包括解析游戏文件格式等内容。位置查找和移动生成在C ++版本中有很多mechanical sympathy,应用所有技巧无法弥补:

  • 编译时优化
  • 非共享泛型(单声道特定 - 请参阅here, e.g.
  • 不安全代码(固定数组,原始指针),
  • 未经检查的块(如数组边界/算术溢出
  • 值类型数组和ref传递
  • 简短,无法使用的功能
  • 垃圾预防(预先分配的'领域'中的自定义分配(仅预先分配大型结构阵列)

也就是说,使用通用集合带来的性能优势是显着的,特别是List<T> where T : struct。但是请注意上面链接中的警告(特别是对于new约束,由于代码共享而在MS .NET上具有相当可悲的性能;它基本上与使用反射调用构造函数一样慢,即使对于值类型也是如此)。

YMMV,但最后我会说

  

1。 使用C#方式。如果必须进行优化,请使用C#方式

     

2。 如果所有其他方法都失败了,请求P / Invoke
(如果您定位Windows,C ++ / CLR是一个最佳点)< / SUP>

答案 2 :(得分:0)

我会在您的基类上使用泛型。这会破坏你代码中的某些内容吗?

void Main()
{
    var factory = new PieceFactory<Rook, int>(20);
    factory.GetPiece().Dump();
}

abstract class Piece<TValue>
{
    public TValue Value { get; set; }
}

class Rook : Piece<int>
{
    public int Capture()
    {
        // Do something...
        return base.Value;
    }
}

class Pawn : Piece<string>
{
    public string EnPassant()
    {
        // Do something...
        return base.Value;
    }
}

class PieceFactory<TKey, TValue> where TKey : Piece<TValue>, new()
{
    private readonly TKey piece;

    public PieceFactory(TValue value)
    {
        this.piece = new TKey();
        this.piece.Value = value;
    }

    public TKey GetPiece()
    {
        return this.piece;
    }
}

我还在您的工厂中添加了一些访问关键字(例如thisbase)和readonly修饰符。