我想知道在C#中链接构造函数时如何更改执行顺序。我见过的唯一方法需要在当前构造函数之外首先调用链式构造函数。
具体来说,请采用以下示例:
public class Foo {
private static Dictionary<string, Thing> ThingCache = new Dictionary<string, Thing>();
private Thing myThing;
public Foo(string name) {
doSomeStuff();
if (ThingCache.ContainsKey(name)) {
myThing = ThingCache[name];
} else {
myThing = ExternalStaticFactory.GetThing(name);
ThingCache.Add(name, myThing);
}
doSomeOtherStuff();
}
public Foo(Thing tmpThing) {
doSomeStuff();
myThing = tmpThing;
doSomeOtherStuff();
}
}
理想情况下,我希望通过这样做来减少代码重复(请注意,我承认在这个人为的示例中,没有保存太多代码,但我正在使用可以获得更多好处的代码。我使用此示例清晰度):
public class Foo {
private static Dictionary<string, Thing> ThingCache = new Dictionary<string, Thing>();
private Thing myThing;
public Foo(string name) {
if (ThingCache.ContainsKey(name)) {
this(ThingCache[name]);
} else {
this(ExternalStaticFactory.GetThing(name));
ThingCache.Add(name, myThing);
}
}
public Foo(Thing tmpThing) {
doSomeStuff();
myThing = tmpThing;
doSomeOtherStuff();
}
}
这在VB .Net中是可行的,但是C#不允许我在另一个构造函数的中间调用构造函数 - 仅在开始时使用Foo():this()语法。
所以我的问题是,如何在链接构造函数时控制构造函数调用的顺序,而不是使用冒号语法,而冒号语法只能先调用其他构造函数?
答案 0 :(得分:8)
您不能在其他构造函数中调用构造函数。构造函数只能将另一个构造函数链接到它之前直接调用。
但是,要解决您的特定问题,您可以创建一个私有构造函数,它可以同时接受两种类型的参数,并让您的两个原始构造函数都将这一个简单地链接起来,为缺少的参数传递null。
这比调用私有初始化方法更有优势,它可以很好地与readonly
字段一起使用(即如果myThing
是readonly
字段,它仍然有效):
public class Foo
{
private static Dictionary<string, Thing> ThingCache =
new Dictionary<string, Thing>();
private Thing myThing;
public Foo(string name)
: this(null, name)
{
}
public Foo(Thing tmpThing)
: this(tmpThing, null)
{
}
private Foo(Thing tmpThing, string name)
{
if (tmpThing == null && name == null)
{
throw new System.ArgumentException(
"Either tmpThing or name must be non-null.");
}
doSomeStuff();
if (tmpThing != null)
{
myThing = tmpThing;
}
else
{
if (ThingCache.ContainsKey(name))
{
myThing = ThingCache[name];
}
else
{
myThing = ExternalStaticFactory.GetThing(name);
ThingCache.Add(name, myThing);
}
}
doSomeOtherStuff();
}
}
如果您使用的是C#4.0,也可以使用命名或可选参数:
答案 1 :(得分:7)
我想知道在C#中链接构造函数时如何更改执行顺序。
你没有。 C#中没有这样的功能。
已经有一种以任意顺序调用任意代码的机制:制作一堆方法并按照你喜欢的顺序调用它们。
这是我关于这个主题的文章更详细的内容。
http://blogs.msdn.com/b/ericlippert/archive/2010/01/28/calling-constructors-in-arbitrary-places.aspx
如果构造函数链接设计原则的主题让您感兴趣,那么您可能还想阅读
和
答案 2 :(得分:1)
您在类中创建私有初始化方法,并让构造函数逻辑调用这些方法。
class Foo
{
public Foo(string name)
{
InitializeBefore();
if (ThingCache.ContainsKey(name))
{
myThing = ThingCache[name];
} else
{
myThing = ExternalStaticFactory.GetThing(name);
ThingCache.Add(name, myThing);
}
InitializeAfter();
}
public Foo(Thing tmpThing)
{
InitializeBefore();
myThing = tmpThing;
InitializeAfter();
}
private void InitializeBefore()
{
doSomeStuff();
// and any other calls you want before
}
private void InitializeAfter()
{
doSomeOtherStuff();
// and any other calls you want at the end of the constructor
}
}
答案 3 :(得分:0)
你必须使用一种方法。最直接的翻译是:
public class Foo {
private static Dictionary<string, Thing> ThingCache = new Dictionary<string, Thing>();
private Thing myThing;
public Foo(string name) {
if (ThingCache.ContainsKey(name)) {
Init(ThingCache[name]);
} else {
Init(ExternalStaticFactory.GetThing(name));
ThingCache.Add(name, myThing);
}
}
public Foo(Thing tmpThing) {
Init(tmpThing);
}
private void Init(Thing tmpThing) {
doSomeStuff();
myThing = tmpThing;
doSomeOtherStuff();
}
}
至少只要你没有只读字段。我不得不承认,在任意位置调用其他构造函数的语法都有其优点。