C# 构造函数链接 - 更改执行顺序

发布于 2024-10-26 13:51:09 字数 1334 浏览 5 评论 0原文

我想知道在 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() 语法。

所以我的问题是,在链接构造函数时如何控制构造函数调用的顺序,而不是使用只能先调用另一个构造函数的冒号语法?

I want to know how to change the order of execution when chaining constructors in C#. The only methods I have seen require the chained constructor to be called first, outside of the current constructor.

Specifically, take the following example:

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();
  }
}

Ideally, I'd like to reduce code repetition by doing this (note, I admit that in this contrived example, not much code is saved, but I am working with code that would benefit much more. I use this example for clarity):

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();
  }
}

This is possible in VB .Net, but C# doesn't let me call a constructor in the middle of another constructor - only at the beginning using the Foo() : this() syntax.

So my question is, how does one control the order of constructor calling when chaining constructors, rather than using the colon syntax, which can only call the other constructor first?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

表情可笑 2024-11-02 13:51:09

您不能在其他构造函数内调用构造函数。构造函数只能链接另一个构造函数在它之前直接调用。

但是,为了解决您的特定问题,您可以创建一个可以接受两种类型参数的私有构造函数,并让两个原始构造函数都简单地链接这个构造函数,为缺少的参数传递 null 。

与调用私有初始化方法相比,它的优点是它可以很好地与 readonly 字段配合使用(即,如果 myThingreadonly 字段,它仍然有效):

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,您还可以使用命名参数或可选参数:

http:// msdn.microsoft.com/en-us/library/dd264739.aspx

You can't call constructors inside other constructors. A constructor can only chain another constructor to be called directly before it.

However, to solve your particular issue, you can make a private constructor that can accept both a types of argument, and have your two original constructors both simply chain this one, passing null for the missing argument.

This has the advantage over calling private initialisation methods that it plays nicely with readonly fields (i.e. it still works if myThing is a readonly field):

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();
    }
}

You could also use named or optional arguments if you are using C# 4.0:

http://msdn.microsoft.com/en-us/library/dd264739.aspx

婴鹅 2024-11-02 13:51:09

我想知道在 C# 中链接构造函数时如何更改执行顺序。

你不知道。 C#中没有这样的功能。

已经有一种以任意顺序调用任意代码的机制:创建一堆方法并按照您喜欢的顺序调用它们。

这是我关于该主题的文章,其中包含更多详细信息。

http://blogs .msdn.com/b/ericlippert/archive/2010/01/28/calling-constructors-in- Arbitrary-places.aspx

如果您对构造函数链设计原则主题感兴趣,那么您可能还想阅读

< a href="http://blogs.msdn.com/b/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one. aspx" rel="nofollow">http://blogs.msdn.com/b/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors- part-one.aspx

http://blogs.msdn.com/b/ericlippert/archive/2008/02/18/why-do-initializers-run-in -相反顺序作为构造函数第二部分.aspx

I want to know how to change the order of execution when chaining constructors in C#.

You don't. There is no such feature in C#.

There already is a mechanism for calling arbitrary code in an arbitrary order: make a bunch of methods and call them in the order you like.

Here's my article on the subject going into more detail.

http://blogs.msdn.com/b/ericlippert/archive/2010/01/28/calling-constructors-in-arbitrary-places.aspx

If the topic of constructor chaining design principles interests you then you might also want to read

http://blogs.msdn.com/b/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx

and

http://blogs.msdn.com/b/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx

浅听莫相离 2024-11-02 13:51:09

您在类中创建私有初始化方法,并让构造函数逻辑调用这些方法。

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
 }

}

You create private initialization methods inside your class and have your constructor logic call those methods.

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
 }

}
浅沫记忆 2024-11-02 13:51:09

你必须使用一种方法。最直接的翻译是:

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();
  }
}

至少只要你没有只读字段。我必须承认,在任意位置调用其他构造函数的语法有其优点。

You have to use a method. The most straightforward translation would be:

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();
  }
}

At least as long as you have no readonly fields. I have to admit, that a syntax to call other constructors at arbitrary locations has its advantages there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文