Как работать с инициализацией объекта и классами в C # - PullRequest
0 голосов
/ 04 октября 2011

У меня есть класс

  class TestFixture
    {
        public string a { get; set; }
        public int b { get; set; }
        public int c { get; set; }
        public string d { get; set; }

        public string e { get ; set ; }
        public int f { get; set; }
        public int g { get; set; }
        public bool h { get; set; }
        public string i { get; set; }
        public bool j { get; set; }
        public bool k { get; set; }

        public TestFixture()
        {
            e= dosomething(a, b);
            f= false;
            g = DateTime.Now.ToString("yyMMddhhmmss");
            h= TestName.Equals("1") && b.Equals("2") ? 1000 : 1;
            i= 10000000;
            j= a.Equals("FOT");
            k = false;
        }
    }

Я хочу определить новую TestFixture как SO

new TestFixture { a = "", b = 1, c=2, d="" };

в то время как остальные свойства должны быть определены автоматически, как написано в конструкторе.

Возможно ли это?

Ответы [ 3 ]

4 голосов
/ 04 октября 2011

Да, это возможно. Использование инициализатора объекта не пропускает вызов конструктора.

TestFixture fixture = new TestFixture() // or just new TestFixture { ... }
{
    a = "", 
    b = 1, 
    c = 2, 
    d = "" 
};

Это вызовет определенный вами конструктор, а затем установит a, b, c и d в инициализаторе вашего объекта.


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

Отладка в Visual Studio


Refactored:

public class TestFixture
{
    public string a { get; set; }
    public int b { get; set; }
    public int c { get; set; }
    public string d { get; set; }

    // dosomething should check for null strings
    public string e { get { return dosomething(a, b); } }
    public int f { get; set; }
    public int g { get; set; }
    public bool h 
    {
        get { return TestName.Equals("1") && b.Equals("2") ? 1000 : 1; }
    }
    public string i { get; set; }
    public bool j { get { return a != null && a.Equals("FOT"); } }
    public bool k { get; set; }

    public TestFixture(string a, int b, int c, string d) 
        : this() 
    {
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
    }

    public TestFixture()
    {
        f = false;
        g = DateTime.Now.ToString("yyMMddhhmmss");
        i = 10000000;
        k = false;
    }
}
1 голос
/ 04 октября 2011

@ hunter's ответ правильный, вы можете использовать синтаксис инициализатора объекта, и эти свойства будут установлены после запуска вашего конструктора.Тем не менее, я хотел бы указать на некоторые недостатки, которые вы можете иметь с вашим кодом

public TestFixture()
{
    e= dosomething(a, b);
    f= false;
    g = DateTime.Now.ToString("yyMMddhhmmss");
    h= TestName.Equals("1") && b.Equals("2") ? 1000 : 1;
    i= 10000000;
    j= a.Equals("FOT");
    k = false;
}

Этот код не устанавливает a или b, но у вас есть вещи, которые зависят от их значений (e, g, j).Синтаксис инициализатора объекта не будет полезен здесь, вы должны иметь правильные значения по умолчанию для этих значений, если другие значения в конструкторе будут зависеть от них.

Например, когда вы пишете var obj = new Bar() { A = "foo" };, это расширится до

var obj = new Bar(); // constructor runs 
obj.A = "Foo"; // a is set 

Очевидно, что код в конструкторе, который смотрит на A, не увидит значение "Foo".Если вам нужно , чтобы увидеть это значение, стратегия инициализации объекта не поможет.Вам нужна перегрузка конструктора , которая принимает значение для сохранения в A.

var obj = new Bar("Foo");
0 голосов
/ 04 октября 2011

Если я вас правильно понял, вы бы хотели, чтобы свойства a, b, c и d были инициализированы с заданными значениями до запуска конструктора. К сожалению, это невозможно, так как конструктор по умолчанию всегда запускается перед инициализаторами объектов. Я советую вам сделать что-то вроде этого:

class TestFixture
{
    //... properties

    public TestFixture()
    {
        this.init();
    }

    public TestFixture(string a, int b, int c, string d)
    {
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;

        this.init();
    }

    private void init()
    {
        e= dosomething(a, b);
        f= false;
        g = DateTime.Now.ToString("yyMMddhhmmss");
        h= TestName.Equals("1") && b.Equals("2") ? 1000 : 1;
        i= 10000000;
        j= a.Equals("FOT");
        k = false;
    }
}

Таким образом, вы можете инициализировать свойства a, b, c и d до запуска другого кода инициализатора.

...