【问题标题】:BaseClass with instance counter带有实例计数器的 BaseClass
【发布时间】:2018-10-18 17:23:01
【问题描述】:

我有一个基类和几个派生类(例如BaseChildA : Base)。每次创建 ChildA 类的实例时,我都希望为它分配一个唯一的实例编号(类似于关系数据库中的自动增量 ID,但对于我的类在内存中而不是在数据库中)。

我的问题与this one 类似,但有一个明显的区别:我希望基类 自动处理此问题。对于我的每个派生类(ChildA、ChildB、ChildC 等),我希望基类维护一个单独的计数,并在创建该派生类的新实例时递增。

所以,我的Base 类中保存的信息最终可能会如下所示:

ChildA,5
ChildB,6
ChildC,9

如果我随后实例化一个新的 ChildB (var instance = new ChildB();),我希望 ChildB 被分配 id 7,因为它是从 6 开始的。

然后,如果我实例化一个新的 ChildA,我希望 ChildA 被分配 id 6。

-

如何在 Base 类的构造函数中处理这个问题?

【问题讨论】:

  • 你已经尝试了什么?你具体卡在哪里了?
  • @SerhiiVoichyk 这不是那个的副本。另一个问题不涉及派生类
  • @SerhiiVoichyk - 几乎所有这些答案都使用单个静态变量,这在我们试图将功能放入基类的地方不起作用
  • @Mobz,更好地解释你的问题,展示你的尝试,我相信这将被重新打开
  • 您能否将此信息与一些示例类一起添加到您的问题中,这些示例类显示您的类层次结构以及应该在哪里访问/定义计数器?让您更轻松地了解您的故事。

标签: c#


【解决方案1】:

您可以在基类中使用静态Dictionary<Type, int>,您可以在其中按类型跟踪派生实例。由于this 将是派生类型,您可以使用this.GetType() 作为字典中的键。

class Base
{
    static Dictionary<Type, int> counters = new Dictionary<Type, int>();
    public Base()
    {
        if (!counters.ContainsKey(this.GetType()))
            counters.Add(this.GetType(), 1);
        else
            counters[this.GetType()]++;
        Console.WriteLine(this.GetType() + " " + counters[this.GetType()]);
    }
}

class Derived : Base
{
}

class Derived2 : Base
{
}

public static void Main()
{
    new Derived();
    new Derived2();
    new Derived();
}

输出:

Derived 1 
Derived2 1
Derived 2

为了线程安全,您可以使用ConcurrentDictionary&lt;K,V&gt; 而不是Dictionary&lt;K,V&gt;

【讨论】:

  • 您应该使用counters.TryGetValue 而不是counters.ContainsKey。这将防止两次查找密钥。
  • 你是问还是说?这是你的答案,我只是在评论它。如果您认为 concurrentDictionary 是更好的解决方案,则应将其编辑到您的答案中。
  • @ZoharPeled 嗯,问题中没有明确提到,所以我不会特别考虑这个。
  • 感谢@Adrian 的出色解决方案!它现在是我代码的一部分并且效果很好!谢谢大家的cmets!感谢 John 让我的问题对 Stackoverflow 更友好 - 这是我肯定落后的技能!
【解决方案2】:

或者线程安全的版本

public class BaseClass
{
   public static ConcurrentDictionary<Type,int> Counter = new ConcurrentDictionary<Type, int>();   
   public BaseClass() => Counter.AddOrUpdate(GetType(), 1, (type, i) => i + 1);
}

用法

for (int i = 0; i < 2; i++)
   Console.WriteLine("Creating " + new A());

for (int i = 0; i < 4; i++)
   Console.WriteLine("Creating " + new B());

for (int i = 0; i < 1; i++)
   Console.WriteLine("Creating " + new C());

foreach (var item in BaseClass.Counter.Keys)
   Console.WriteLine(item + " " + BaseClass.Counter[item] );

输出

Creating ConsoleApp8.A
Creating ConsoleApp8.A
Creating ConsoleApp8.B
Creating ConsoleApp8.B
Creating ConsoleApp8.B
Creating ConsoleApp8.B
Creating ConsoleApp8.C
ConsoleApp8.A 2
ConsoleApp8.C 1
ConsoleApp8.B 4

Full Threaded Demo Here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 2018-06-28
    • 1970-01-01
    相关资源
    最近更新 更多