如何判断对象初始化程序何时完成

时间:2012-02-09 04:33:49

标签: c# oop object-initializers

我有各种派生对象,我希望用户能够使用对象初始化器。我有一个“初始化”属性,我希望在设置这些字段时为true,然后我希望之后将Initializing属性设置为false。

如何判断对象初始化程序何时能够执行此操作?

class Foo
{    
    Public Foo(string p1, string p2)
    {
        Initializing = true;
        Property1 = p1;
        Property2 = p2;
        Initializing = false;
    }

    bool Initializing;

    string _property1;
    string Property1 
    {
        get { return _property1; } 
        set { _property1 = value; DoSomething(); }
    }

    string Property2 { get; set; }

    public void DoSomething()
    {
        if(Initializing) return; // Don't want to continue if initializing
        // Do something here
    }
}

在上面的示例中,如果使用构造函数,它可以正常工作。但是如何使用对象初始化器以相同的方式工作是一个问题。

编辑:对于你所有的反对者,这里有其他人正在寻找我正在追求的东西 - http://blogs.clariusconsulting.net/kzu/how-to-make-object-initializers-more-useful/

不幸的是,它确实看起来像是不可能的。

6 个答案:

答案 0 :(得分:4)

如果您确实需要跟踪对象的初始化,那么您需要手动实现该逻辑。一种方法是复制WinForms代码生成器使用的方法。对象在希望批量更新属性时公开ISupportInitialize接口的位置。所以用法就像......

var x = new Foo();
x.BeginInit();
x.Property1 = 1;
x.Property2 = 2;
x.EndInit();

答案 1 :(得分:3)

设置任何标志都没有意义。在初始化程序运行之前,您无法访问对象。例如:

var object = new object() { Prop1 = "Boo" }

由于在设置Prop1之后无法访问从new返回的引用,因此无法访问任何属性,因此无需控制访问权限或担心它是否“完成”。

虽然,我想我可以看到你可能会有这样的事情:

public class Foo {
    private int _value;
    public int Bar {
        set {
            _value = value * Baz; // don't want to do this if initializing
        }
    }

    public int Baz { get; set; }
}

如果这是您所关注的问题,那么您就错误地设计了对象。属性不应该像这样的副作用。没有办法知道是否所有的初始化都已完成。

答案 2 :(得分:1)

这个问题毫无意义。对象初始化器语法只是语法糖的简写。

此:

var myInstance = new someClass()
{
    Prop1 = "",
    Prop2 = "",
    Prop3 = "",
    Prop4 = "",
    Prop5 = ""
}

与此完全相同:

var myInstance = new someClass();
myInstance.Prop1 = "";
myInstance.Prop2 = "";
myInstance.Prop3 = "";
myInstance.Prop4 = "";
myInstance.Prop5 = "";

无法检测到“完成”。

你想做什么我们可以做的事情:

class someClass()
{
  public string AStringProperty { get; set; }
  public bool IsInitiazlied 
  {
    return string.IsNullOrWhitespace(this.AStringProperty);
  }
}

或者,让ctor取值的初始状态,然后保证你的设置。

class someClass()
{
  public string AStringProperty { get; set; }
  public someClass(string AStringPropertyInit)
  {
      this.AStringProperty = AStringPropertyInit;
  }
}

修改

class Foo
{    
    Public Foo(string p1, string p2)
    {

        _property1= p1; //set the backing store directly, 
                        //skips the side effect in the setter
        Property2 = p2;

        DoSomething(); // now cause the side effect
                       // we know everything is setup
    }



    string _property1;
    string Property1 
    {
        get { return _property1; } 
        set { _property1 = value; DoSomething(); }
    }

    string Property2 { get; set; }

    public void DoSomething()
    {
        // Do something here
    }
}

答案 3 :(得分:1)

由于对象初始化只是语法糖,因此无法区分它和普通属性集。我也不能想到一个合理的案例,你想以不同的方式对待它们。

也就是说,如果你说必须设置至少1个x属性(无论是简写还是简写语法),那么你可以在ctor中设置初始化为true,然后在每个属性集上将其设置为false。

答案 4 :(得分:1)

您可以让DoSomething方法验证它是否具有完成工作所需的信息,而不是依赖于显式属性来告诉您对象何时初始化。你的例子很粗糙,我希望你的实际实现更复杂,所以我只假设必须将Property1Property2分配给某些东西(意思就是不是继续前空字符串):

class Foo
{    
    public Foo(string p1, string p2)
    {
        Property1 = p1;
        Property2 = p2;
    }

    string Property1 { get; set; } 
    string Property2 { get; set; }

    public void DoSomething()
    {
        // *** Replace this with something valid to your real code
        if(!string.IsNullOrEmpty(Property1) || !string.IsNullOrEmpty(Property2)) 
            return; // Don't want to continue if not initialized
        // Do something here
    }
}

<强>更新

不了解您实际使用的对象模型,这里有一个基于整个框架中广泛使用的模型的可能替代方案:

class Foo
{
    public void DoSomething(FooConfig config)
    {
    }
}

class Foo
{
    private FooConfig config_;

    public Foo(FooConfig config)
    {
        config_ = config;
    }

    public void DoSomething()
    {
    }
}

定义FooConfig的位置:

class FooConfig
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

使用以下方式调用DoSomething

(new Foo()).DoSomething(new FooConfig() { Property1 = "abc"; Property2 = "def"; });

OR

(new Foo(new FooConfig() { Property1 = "abc"; Property2 = "def"; })).DoSomething();

可以轻松更改此设置,以适应FooFooConfig上的构造函数使用情况。

答案 5 :(得分:0)

对象初始化器只是创建对象和在其上设置一组属性的简写。问“何时完成”并不合理。

如果您希望对象的状态依赖于初始化的特定属性集,那么您可以为每个属性的setter添加代码并在内部跟踪它。但这确实取决于你想要实现的目标。

<强>更新

只是阅读你对@asawyer的答案的评论。没有办法判断是否在初始化程序中设置了属性。只是为了说明 - 这里有三段完全相同的代码,除了你似乎想要一个不同的行为。

var someVar1 = new SomeClass()
               {
                    Prop1 = "value1";
                    Prop2 = "value2";
               };

var someVar2 = new SomeClass()
               {
                    Prop1 = "value1";
               };
someVar2.Prop2 = "value2";

var someVar3 = new SomeClass();
someVar3.Prop1 = "value1";
someVar3.Prop2 = "value2";

跟踪单个属性设置器的执行情况并不难,并且除了第一次执行外,还会触发一些副作用,但是如果客户端更改初始对象配置,我只想触发副作用在ctor完成后没有任何意义。