6

据我所知,您不能将参数传递给 C# 中的静态构造函数。但是,在创建类的实例之前,我确实需要传递 2 个参数并将它们分配给静态字段。我该怎么做?

4

3 回答 3

9

这可能是对……工厂方法的呼吁!

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”是否已适当初始化(或未初始化)。

于 2010-05-04T16:27:56.140 回答
4

您不能将参数传递给静态构造函数,但可以通过泛型类型参数将参数传递给类本身。

这个想法有点疯狂,但是,无论如何我都会把它扔在那里。

使类成为泛型(使用将提供参数类型的 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 的单次初始化保证。

一个警告- 你应该审查你的结构吗?

说了这么多——不过请记住,因为你只能参数化静态一次(或者在这种情况下,每个唯一参数化的静态泛型)——我会问自己为什么不直接提取获取参数的代码以提供给静态,并首先将其放在静态构造函数中?这样,您实际上就不必求助于这样的奇怪模式!

于 2010-05-04T20:47:23.407 回答
3

我假设您的意思是类的静态成员?在这种情况下,您可以这样做:

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 之前需要遵守纪律。

您可能会遵循的另一种模式如下所示:

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. 
于 2010-05-04T16:22:54.187 回答