クラスのインスタンスの作成を制限しますか?
質問
C#を使用しています。任意の c#.net プロジェクト (デスクトップまたは Web ベース) に含めることができるクラスを作成しましたが、クラスのそのアプリケーションには 10 個のオブジェクトのみが作成されるようにしたいと考えています。オブジェクト インスタンスが 10 を超えて作成された場合は、エラーが発生するか、単純に動作しません。
2 つの状況が考えられます。
- 任意のプロジェクトにmyclass.csファイルを含めます
- クラスを DLL にバンドルし、任意のアプリケーションに含めます。
どちらの状況でも、アプリケーション内でクラスのインスタンスが 10 個を超えて作成されると、エラーが発生するはずです。
この質問は先生がしたもので、インターネットで答えを探すように言われました。試してみましたが、この問題の解決策はどこにも見つかりませんでした。オブジェクトを制限できるとは聞いていません。
可能ですか?可能であれば、どのようにして可能ですか?
ありがとう
解決
作成されたインスタンスの数を含む静的変数を保持します。オブジェクトが構築されるたびにその数値が増加します。オブジェクト IDisposable を作成し、Dispose() を呼び出すたびにその数値をデクリメントします。スレッドセーフにしたい場合は、++ と -- の代わりに Interlocked.Increment() と Interlocked.Decrement() を使用してこの変数の値を変更します。
他のヒント
何らかの形で望んでいらっしゃると思いますが、 マルチトンパターン.
マルチトン パターンはシングルトン パターンのバリエーションですが、オブジェクトの n 個のインスタンスが許可されます。シングルトン クラスに単一のインスタンスを保持する静的変数があるのと同じように、マルチトンは、インスタンスへのアクセス方法に応じて、インスタンスの静的配列またはマップを使用して実装されることがよくあります。配列では数値アクセスのみが可能ですが、マップの場合は、インスタンスに文字列キーを提供して名前を付けることができます。
単に使用する必要があります 工場パターン 作成されたインスタンスの数のカウンターを使用します。その後、ファクトリ メソッドは例外をスローするか null を返します。
例:
public class Foobar
{
private static int numInstances = 0;
public static Foobar CreateFoobar()
{
if (numInstances++ < 10)
{
return new Foobar();
}
return null;
}
protected Foobar()
{
...
}
}
上記の方法は、単一インスタンスのアプリケーションでは完全にうまく機能しますが、複数インスタンスのアプリケーションの場合は、おそらく セマフォ (実装は System.Threading
)、これはまさにこの種の状況 (リソース/オブジェクトへのアクセスを制限する) を対象としています。これにより、クラスの複数のインスタンスがほぼ同時にリクエストされ、カウント チェックが失敗するという問題が回避されます。
私なら作成します 静的 整数を取得し、新しいオブジェクトをインスタンス化するときにそれを更新します。
class YourClass
{
static int Count = 0;
public YourClass()
{
Count++;
if(Count > 10)
{
//throw exception
}
}
}
クラスで静的なカウンターを取得し、カウントが 10 を超える場合はクラス コンストラクターで例外をスローします。
インスタンスを破棄するには、静的アンロード メソッド (AppDomain と同様) も作成します。アンロード メソッドで IDisposable の実装を呼び出し、Interlocked.Decrement を使用してカウンタをデクリメントし、インスタンスも破棄します。
(インスタンスの数を制限している場合、インスタンス内に管理するリソースがあると想定しています。)
ジェネリックスを使用して、さまざまなクラスのインスタンスを制限するためにファクトリ クラスを再利用できるようにすることもできます。制約を使用して、インスタンスに IDisposible を実装し、デフォルトのコンストラクターを持たせる必要があります。実際のインスタンスを返す非静的プロパティも提供します。
public class foo : IDisposable
{
public foo() { ; }
public string Name;
public void Dispose() { ; }
// Real class would free up instance resources
}
LimitedInstance< foo > li = LimitedInstance< foo >.CreateInstance();
li.Instance.Name = "Friendly Name for instance";
// do stuff with li
LimitedInstance< foo >.UnloadInstance( ref li );
唯一の問題は、C# では代入演算子をオーバーロードできないことです。したがって、次のようにすると:
li = null;
アンロード メソッドを呼び出す代わりに、インスタンスはヒープ上に残り、GC が発生するまでインスタンス数のカウンターはデクリメントされません。