私の知る限り、C# の静的コンストラクターにパラメーターを渡すことはできません。ただし、クラスのインスタンスを作成する前に、2 つのパラメーターを渡して静的フィールドに割り当てる必要があります。どうすればいいですか?
3 に答える
これは、... Factory Method の呼び出しかもしれません!
class Foo
{
private int bar;
private static Foo _foo;
private Foo() {}
static Foo Create(int initialBar)
{
_foo = new Foo();
_foo.bar = initialBar;
return _foo;
}
private int quux;
public void Fn1() {}
}
必要に応じて、'bar' が既に初期化されている (またはされていない) ことを確認することができます。
パラメーターを静的コンストラクターに渡すことはできませんが、ジェネリック型パラメーターを介して、パラメーターをクラス自体に渡すことができます。
このアイデアは少しクレイジーですが、とにかく放り出します。
クラスをジェネリックにし (パラメーター型を提供する TypeParam を使用)、ジェネリック制約を配置します (コード例の詳細)。その後、必要なパラメーター値を読み取るために使用できる仮想を含む新しいパラメーター型を派生させます。することが。
//base parameter type - provides the 'anchor' for our generic constraint later,
//as well as a nice, strong-typed access to our param values.
public class StaticParameterBase
{
public abstract string ParameterString{ get; }
public abstract MyComplexType ParameterComplex { get; }
}
//note the use of the new() generic constraint so we know we can confidently create
//an instance of the type.
public class MyType<TParameter> where TParameter:StaticParameterBase, new()
{
//local copies of parameter values. Could also simply cache an instance of
//TParameter and wrap around that.
private static string ParameterString { get; set; }
private static MyComplexType ParameterComplex { get; set; }
static MyType()
{
var myParams = new TParameter();
ParameterString = myParams.ParameterString;
ParameterComplex = myParams.ParameterComplex;
}
}
//e.g, a parameter type could be like this:
public class MyCustomParameterType : StaticParameterBase
{
public override string ParameterString { get { return "Hello crazy world!"; } }
public override MyComplexType { get {
//or wherever this object would actually be obtained from.
return new MyComplexType() { /*initializers etc */ };
}
}
}
//you can also now derive from MyType<>, specialising for your desired parameter type
//so you can hide the generic bit in the future (there will be limits to this one's
//usefulness - especially if new constructors are added to MyType<>, as they will
//have to be mirrored on this type as well).
public class MyType2 : MyType<MyCustomParameterType> { }
//then you'd use the type like this:
public static void main()
{
var instance = new MyType<MyCustomParameterType>();
//or this:
var instance2 = new MyType2();
}
カスタム型属性を使用するソリューションを型パラメーターに適用することを検討しましたが、これは簡単に優れた方法です。ただし、クラスを常に汎用パラメーター型で使用することになります (派生 + 特殊化のトリックを使用できない場合) - おそらく好みには不器用です。
また、静的初期化の回避策を作成する必要がないため、ここで紹介する他のソリューションよりもこれをお勧めします。.Net のシングルタイム初期化の保証を引き続き使用できます。
警告の言葉- 構造を見直す必要がありますか?
とはいえ、覚えておいてください、静的を一度しかパラメーター化できないため(または、この場合は、一意にパラメーター化された静的ジェネリックごとに)、静的に与えるパラメーターを取得しているコードをプルするだけではない理由を自問します。 、そして最初に静的コンストラクターに配置しますか? そうすれば、実際にこのような奇妙なパターンに頼る必要はありません!
クラスの静的メンバーを意味していると思いますか?その場合、これを行うことができます:
public class MyClass
{
public static int MyInt = 12;
public static MyOtherClass MyOther = new MyOtherClass();
}
これらの静的メンバーは、クラスがインスタンス化される前にインスタンス化されることが保証されています。
複雑なロジックが必要な場合は、静的コンストラクターで行います。
public class MyClass
{
public static int MyInt;
public static MyOtherClass MyOther;
static MyClass()
{
MyInt = 12;
MyOther = new MyOtherClass();
}
}
編集
あなたの編集に基づいて、次のように、クラスをインスタンス化する前に必要なものに値を割り当てるだけです。
public class MyClass
{
public static int MyInt;
public static MyOtherClass MyOther;
}
// elsewhere in code, before you instantiate MyClass:
MyClass.MyInt = 12;
MyClass.MyOther = new MyOtherClass();
MyClass myClass = new MyClass();
つまり、このメソッドでは、MyClass がインスタンス化される前に MyInt と MyOther が設定されるという保証はありません。動作しますが、MyClass をインスタンス化する前に規律が必要です。
従う可能性のある代替パターンの 1 つは、次のようになります。
public class MyClass
{
private static int MyInt;
private static MyOtherClass MyOther;
private static bool IsStaticInitialized = false;
public static InitializeStatic(int myInt, MyOtherClass other)
{
MyInt = myInt;
MyOther = other;
IsStaticInitialized = true;
}
public MyClass()
{
if(!IsStaticInitialized)
{
throw new InvalidOperationException("Static Not Initialized");
}
// other constructor logic here.
}
}
// elsewhere in your code:
MyClass.InitializeStatic(12, new MyOtherClass());
MyClass myClass = new MyClass();
// alternatiavely:
MyClass myClass = new MyClass(); // runtime exception.