Передача статических параметров к классу

Насколько я знаю Вас, банка не может передать параметры статическому конструктору в C#. Однако у меня действительно есть 2 параметра, я должен передать и присвоить их статическим полям, прежде чем я создам экземпляр класса. Как я иду об этом?

6
задан Cody Gray 19 March 2013 в 04:26
поделиться

3 ответа

Это может быть вызов ... фабричного метода!

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() {} 
} 

Вы можете поставить проверку, что «полоса» уже инициализирована (или нет) соответствующим образом.

8
ответ дан 8 December 2019 в 17:19
поделиться

Вы не можете передавать параметры статическому конструктору, но вы можете передавать параметры самому классу - через параметры общего типа.

Немного безумная идея, однако, я все равно ее выскажу.

Сделать класс generic (с TypeParam, который будет предоставлять тип параметра) и наложить на него generic-ограничения (подробности в примере кода), затем вывести новый тип параметра, который содержит виртуалки, которые можно использовать для чтения того, какими должны быть значения параметров.

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

Я рассматривал решение, при котором пользовательские атрибуты типа применяются к параметру типа, однако этот способ легко может быть лучше. Однако теперь вы будете использовать свой класс всегда с общим типом параметра (если только вы не сможете использовать трюк deriving+specialisation) - возможно, слишком неуклюже для вашего вкуса.

Я бы также предпочел этот вариант другим представленным здесь решениям, поскольку он не требует создания обходных путей для статической инициализации - вы все еще можете использовать гарантию .Net на однократную инициализацию.

Слово предупреждения - следует ли вам пересмотреть свою структуру?

Все это сказано - помните, однако, что поскольку вы можете параметризовать статику только один раз (или, в данном случае, каждый уникально параметризованный статический дженерик) - я бы спросил себя, почему бы просто не вытащить код, который получает параметры для передачи статике, и не поместить его в статический конструктор в первую очередь? Тогда вам не придется прибегать к таким странным шаблонам, как этот!

4
ответ дан 8 December 2019 в 17:19
поделиться

Полагаю, вы имеете в виду статические члены класса? В этом случае вы можете сделать следующее:

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

Edit

На основании вашего редактирования, я бы сказал, просто назначьте значения тем, что они должны быть, прежде чем вы создадите экземпляр класса, например :

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

Тем не менее, этот метод не дает вам гарантии, что MyInt и MyOther установлены до создания экземпляра MyClass. Это будет работать, но перед созданием экземпляра 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. 
2
ответ дан 8 December 2019 в 17:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: