【问题标题】:CRTP implementation in c# [duplicate]C# 中的 CRTP 实现 [重复]
【发布时间】:2023-01-12 23:23:38
【问题描述】:

我正在尝试在 C# 中实现 Curiously recurring template pattern(CRTP)

这是我写的一些代码。

using System;
using System.Collections;
using System.Collections.Generic;


// Curiously recurring template pattern in c#
namespace MyApp
{
    public class Program 
    {
        public static void Main (string[] arg)
        {
            new Child().CallChildMethod();        
        }
    } 

    public abstract class Base <T> where T: Base<T>, new ()
    {
        public void CallChildMethod ()
        {
            T t = (T)this;
            t?.Method ();
        }

        public void Method () 
        {
            Console.WriteLine ("Base Method!");
        }
    }
    
    public class Child: Base <Child> 
    {
        public new void Method ()
        {
            Console.WriteLine ("Child Method!");
        }
    }
}

在输出中我得到

Base Method!

但我的代码应该打印

Child Method!

任何的想法?

预期的

我想访问 base 类中的 child 类对象而不是 overriding 基方法。

【问题讨论】:

  • 请参阅上面的 2 个组合答案,它们应该可以回答您关于为什么会发生这种情况的问题。
  • 另外,为什么不直接使用 virtual/override 的多态性呢? new 是我会说的一种代码味道。
  • @GuruStron 我在更新中覆盖了一个功能,它需要成本!

标签: c# performance class inheritance crtp


【解决方案1】:

您的代码中的问题是 Child 类中定义的方法标有 new 关键字。这告诉 C# 编译器该方法旨在隐藏或覆盖基类中具有相同名称的现有方法。但是,Child 中定义的 Method 实际上并没有覆盖 Base 中定义的 Method,因为它没有 override 关键字。因此,当在 Child 的实例上调用 CallChildMethod 方法时,它调用的是 Base 中定义的方法,而不是 Child 中定义的方法。

要解决此问题,您可以从 Child 中定义的方法中删除 new 关键字,并改为添加 override 关键字。这将正确覆盖 Base 中的方法,以便 CallChildMethod 方法在调用 Child 的实例时调用 Child 中的正确实现。

public class Child: Base <Child> 
{
    public override void Method ()
    {
        Console.WriteLine ("Child Method!");
    }
}

此外,这里您使用的是 CRTP 模式,这很好,但 CRTP 是 C++ 功能,在 C# 中不受本地支持。 C# 有自己的方法来实现类似的结果,例如使用接口、通用约束和多态性。

如果您不想使用 override 关键字,您仍然可以通过让基类的方法调用派生类上的虚拟方法来实现您正在寻找的行为。

您可以通过向 Base 类添加一个虚拟方法来实现这一点,该方法旨在被派生类覆盖,然后从 Base 类的 Method 中调用该方法。在派生类中,您将覆盖此虚拟方法而不是基类中的方法。

这是一个例子:

    public abstract class Base <T> where T: Base<T>, new ()
{
    public void CallChildMethod ()
    {
        T t = (T)this;
        t?.Method ();
    }

    public void Method () 
    {
        Console.WriteLine ("Base Method!");
        DerivedMethod();
    }

    public virtual void DerivedMethod(){}
}

public class Child: Base <Child> 
{
    public void DerivedMethod()
    {
        Console.WriteLine ("Child Method!");
    }
}

在此示例中,当在 Child 的实例上调用 CallChildMethod 时,它会调用 Base 中定义的方法,而后者又会调用 Child 中定义的 DerivedMethod。 通过这种方式,您可以实现与 CRTP 类似的行为,但使用一些不同的方法。

【讨论】:

  • 我想你从chat GPT复制了这个答案我已经提到我不想使用override关键字
猜你喜欢
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多