如何判断对象初始值设定项何时完成
本文关键字:何时完 何判断 判断 对象 | 更新日期: 2023-09-27 18:23:47
我有各种派生对象,我希望用户能够使用对象初始值设定项。 我有一个"正在初始化"属性,我希望在设置这些字段时为 true,然后我希望初始化属性之后设置为 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/
不幸的是,它看起来确实是不可能的。
如果您确实需要跟踪对象的初始化,则需要手动实现该逻辑。一种方法是复制 WinForms 代码生成器使用的代码。其中,当对象希望在批量更新属性时,它们会公开 ISupportInitialize 接口。所以用法是这样的...
var x = new Foo();
x.BeginInit();
x.Property1 = 1;
x.Property2 = 2;
x.EndInit();
设置任何标志都没有意义。 在初始值设定项运行之前,无法访问对象。 例如:
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; }
}
如果这是您关心的,那么您设计的对象不正确。 属性不应该有这样的副作用。 没有办法知道是否完成了所有的初始化。
由于对象初始化只是语法糖,因此您无法区分它与普通属性集之间的区别。我也想不出一个合理的案例,你想区别对待他们。
也就是说,如果你说必须至少设置 x 个属性中的 1 个(无论是手写语法还是速记语法(,那么您可以在 ctor 中将初始化设置为 true,然后在每个属性集上将其设置为 false。
毫无意义。对象初始值设定项语法只是语法糖的简写。
这:
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
}
}
您可以让 DoSomething
方法验证它是否具有完成其工作所需的信息,而不是依赖于显式属性来告诉您对象何时初始化。你的例子很粗糙,我希望你的实际实现更复杂,所以我只是假设必须将Property1
和Property2
分配给某些东西(这意味着在继续之前不是一个空字符串(:
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"; });
或
(new Foo(new FooConfig() { Property1 = "abc"; Property2 = "def"; })).DoSomething();
这可以很容易地更改以适应Foo
或FooConfig
上的构造函数使用。
对象初始化器只是创建对象并在其上设置一堆属性的简写。 问"什么时候完成"是没有意义的。
如果您希望对象的状态依赖于要初始化的特定属性集,则可以将代码添加到每个属性的 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";
跟踪单个属性 setter 的执行并不难,并在除第一次执行之外的所有执行中触发一些副作用,但要说我只想在客户端更改初始对象配置时触发副作用在 ctor 完成后毫无意义。