限制 class 实例化

Restrict class instantiation

在 C# 中,有没有办法停止实例化 class,比如说在 'n' 实例化之后?这 link 没有多大帮助。

关于尝试一些事情,我正在考虑将 class 设置为静态,但是 'n' 实例化必须在停止实例化之前完成。是否可以通过反射?

您可能有一个私有静态计数器,在构造函数中递增它并在达到限制时抛出异常。但请注意,这是一个非常奇怪且很可能是糟糕的设计。 更好的方法是工厂模式

class LimitedInstantiation
    {
        private static int instCounter = 0;
        public LimitedInstantiation()
        {
            instCounter++;
            // limit your number of instances 
            if (instCounter > 3)
            {
                throw new Exception("Limit of instances reached");
            }
        }

        ~LimitedInstantiation()
        {   
            // Reduce your number of instances in the destructor
            instCounter--;
        }
    }

你可以这样测试:

try
{
    var instance1 = new LimitedInstantiation();
    var instance2 = new LimitedInstantiation();
    var instance3 = new LimitedInstantiation();
    // this should fail.
    var instance4 = new LimitedInstantiation();
}
catch (Exception e)
{
    Console.WriteLine(e);
}

您可以使用类似于单例模式的模式(除了我们允许多个实例):

public sealed class LimitedInstantiationsClass
{
    private const int _maxInstantiations = 5;
    private static int _instantiations = 0;
    private static object _lockObject = new object();

    private LimitedInstantiationsClass()
    {
    }

    public static bool TryGetInstance(out LimitedInstantiationsClass instance)
    {
        instance = null;
        if (_instantiations >= _maxInstantiations)
        {
            return false;
        }
        lock (_lockObject)
        {
            if (_instantiations >= _maxInstantiations)
            {
                return false;
            }
            ++_instantiations;
        }
        instance = new LimitedInstantiationsClass();
        return true;
    }
}

本质上,只有 TryInstance 方法可以创建 class* 的实例,因为构造函数是私有的。在 class 中,我们私下跟踪我们提供了多少实例。加锁代码是为了保证这个方法是线程安全的,所以我们最多提供的就是_maxInstantiations(5).

我们检查 _instantiations >= _maxInstantiations 两次的原因是因为这可能会在第一次检查和获取锁之间发生变化。我们在外部进行测试,以避免在无法创建更多实例时获取锁的成本。

TryInstance 达到限制后会 return false。

** 您仍然可以使用反射在别处创建一个,但几乎任何方法都可以做到这一点。

Try it online