将静态参数传递给类

发布于 2024-08-31 10:34:55 字数 77 浏览 7 评论 0原文

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

As far as I know you can can't pass parameters to a static constructor in C#.
However I do have 2 parameters I need to pass and assign them to static fields before I create an instance of a class. How do I go about it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

站稳脚跟 2024-09-07 10:34:56

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

这个想法有点疯狂,不过,无论如何我都会把它扔掉。

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

警告一句话 - 您应该检查您的结构吗?

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

You can't pass parameters to a static constructor, but you can pass parameters to the class itself - via generic type parameters.

Slightly crazy this idea, however, I'll just throw it out there anyway.

Make the class generic (with a TypeParam that will provide a parameter type) and place generic constraints on it (details in code example), then derive a new parameter type, which contains virtuals that you can use to read what they want the parameter values to be.

//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();
}

I did consider a solution that employs custom type attributes applies to a type parameter, however this is easily a better way. However, you'll now be using your class always with a generic parameter type (unless you can use the deriving+specialisation trick) - possibly too clumsy for your liking.

I'd also prefer this over the other solutions presented here as it doesn't require creating any workarounds for the static initialisation - you can still use .Net's guarantee of single-time initialisation.

A word of warning - should you be reviewing your structure?

All that said - remember, though, since you can only parameterise the static once (or in this case, each uniquely parameterised static generic) - I would be asking myself why not just pull the code that is getting the parameters to give to the static, and place it in the static constructor in the first place? That way you don't actually have to resort to strange patterns like this!

鱼忆七猫命九 2024-09-07 10:34:56

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

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. 

I assume you mean static members of a class? In that case, you can do this:

public class MyClass
{
    public static int MyInt = 12;
    public static MyOtherClass MyOther = new MyOtherClass();    
}

Those static members are guaranteed to be instantiated before any class is instantiated.

If you need complex logic, do it in a static constructor:

public class MyClass
{
    public static int MyInt;
    public static MyOtherClass MyOther;
    static MyClass()
    {
        MyInt = 12;
        MyOther = new MyOtherClass();
    }
}

Edit

Based on your edit, I'd say just assign the values to what they need to be before you instantiate the class, like so:

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();

That said, this method gives you no guarantee that MyInt and MyOther are set before MyClass is instantiated. It will work, but requires discipline before instantiating MyClass.

One alternative pattern you might follow looks like this:

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. 
薄情伤 2024-09-07 10:34:55

这可能是对……工厂方法的调用!

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

This may be a call for ... a 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() {} 
} 

You may want to put a check that 'bar' is already initialized (or not) as appropriate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文