我可以将构造函数逻辑与对象初始化器语法一起使用吗?

时间:2017-07-07 21:56:45

标签: c# constructor

即。

MyClass myClass = new MyClass() { Value = 5 };

我有一堆构造函数调用,如上所述,但现在我已经意识到我需要为构造函数添加逻辑,这是一个巨大的疏忽。目前我没有构造函数,所以只是一个空白的隐式默认构造函数。

下面的代码应该解释我的问题。

编辑:我实际上没有进行验证,这只是构造函数逻辑的一个简单示例

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(new Test(1) + " should be true");
        Console.WriteLine(new Test(0) + " should be false");
        Test test = new Test(0) { Value = 1 }; // It allows this syntax, oddly, but the value that's used is the one passed as a parameter
        Console.WriteLine("I wish " + test + " was true");
        // This is what I have currently, but I'd like to add logic like that which exists in the parameterized constructor
        //Test test = new Test() { Value = 1 } // Would ideally function just like Test(1), otherwise I have to go and change every call

        // OUTPUT
        // True should be true
        // False should be false
        // I wish False was true

        Console.ReadLine();
    }
}

class Test
{
    public bool? IsGood { get; }
    public int Value { get; set; }

    // This doesn't currently exist in my class, but I'd like to add it
    public Test(int value)
    {
        if (value == 1)
            IsGood = true;
        else
            IsGood = false;
    }

    public override string ToString()
    {
        return IsGood.ToString();
    }
}

2 个答案:

答案 0 :(得分:4)

首先不要写这样的代码。

我会像这样编写你的代码:

class Test 
{
  public static bool IsValid(int value) 
  {
     return whatever; // test for validity here
  }
  public int Value { get; private set; } // Don't let anyone change it.
  public Test(int value) {
    if (!IsValid(value)) throw new InvalidArgumentException("value");
    this.Value = value;
  }
}

在那里,现在Value始终有效;用户可以提前知道它是否有效;尝试设置无效值会产生异常。这假设Value无法更改。

如果Value可以更改,请按以下方式编写:

class Test 
{
  public static bool IsValid(int value) 
  {
     return whatever; // test for validity here
  }
  private int value;
  public int Value { get { return value; } 
    set 
    {
      if (!IsValid(value)) throw new InvalidArgumentException("value");
      this.value = value;
    }
  }
  public Test(int value) {
    this.Value = value;
  }
}

现在价值再次合法。

如果价值合法是合法的,那么:

class Test 
{
  public bool IsValid 
  {
     get 
     {
       return whatever; // test for validity here
     } // read-only property
  }
  public int Value { get; set; }
  public Test(int value) {
    this.Value = value;
  }
}

现在,该值可以是任何整数,无论​​它是否有效都可以动态测试。

答案 1 :(得分:0)

  

我是否可以在构造函数中使用逻辑时在构造函数外部设置成员?

意义,究竟是什么?

使用对象初始化程序语法,构造函数仍然运行。你甚至可以通过普通的构造函数重载语法(你似乎在展示它,但你说它不在你的类中?)来选择使用哪一个。构造函数中的代码会查看传递给它的参数value,而不是属性Value(它甚至没有设置)。但是,如果您打算让两者一起工作,那么确定...您可以在IsGood属性设置器中的构造函数中设置Value来设置属性。

如果您要这样做,那么我根本不会理解构造函数中的逻辑。只需设置Value属性,让其setter完成剩下的工作:

class Test
{
    public bool? IsGood { get; private set; }

    private int _value;
    public int Value
    {
        get { return _value; }
        set
        {
            _value = value;
            IsGood = _value == 1;
        }
    }

    public Test(int value)
    {
        Value = value;
    }
}

我应该指出,上面的语义与你似乎开始时的语义略有不同。也就是说,Value属性不是只读属性,因此可以随时设置。因此,类似地,IsGood属性可以随时更改。您之前已将其声明为只读,并且只能在构造函数中设置。

从您的问题中不清楚这是否是一个问题。如果您希望IsGood严格只读(即使没有private设置者),那么就不可能按字面意思执行您要求的内容,因为对象初始化程序语法,它依赖于构造函数已经返回后设置成员属性

目前,我假设将private设置器添加到IsGood属性

请注意,由于IsGood显然仅取决于Value的值,您甚至可以像这样实现上述内容:

class Test
{
    public bool? IsGood => _value != null ? _value == 1 : (bool?)null;

    private int? _value;
    public int Value
    {
        get { return _value ?? 0; }
        set { _value = value; }
    }

    public Test(int value)
    {
        Value = value;
    }
}

也就是说,不要为IsGood存储值。只需根据Value属性的当前状态返回适当的值(null,如果它从未设置过true,如果它当前设置为{{} 1}},否则1