: this(foo) syntax in C# constructors?

2019-01-22 20:43发布

问题:

Every now and then, I bump into syntax that I've seen before, but never used. This is one of those times.

Can someone explain the purpose of ":this" or ":base" following a C# constructor method?

For example:

public MyClass(SomeArg arg) : this(new SomethingElse(), arg)
{
}

My gut feeling is that it is used to map a default argument onto another constructor method.

回答1:

You're basically right. this() calls a constructor on the current instance, base() calls the supertype's constructor on current instance. They're generally used to handle constructor overloads so you can add additional options without breaking things out into a separate method.



回答2:

Your gut feeling is right. The syntax is used to call overloaded constructors in the same class:

public class Test
{
    public Test() : this("Called from default constructor") { }
    public Test(String msg)
    {
        Console.WriteLine(msg);
    }
}

The following code:

public static void Main(String[] args)
{
    Test t1 = new Test();
    Test t2 = new Test("Called from Main function");
}

Outputs the following

Called from default constructor
Called from main function

Similarly, : base(someParams) is used to call base constructors.



回答3:

You're right.

: base(...) calls a constructor of the base class.

: this(...) calls another constructor of the defining class. Most of the time it works merely as a facade.



回答4:

Every constructor in a .NET class ensures that a constructor in the class it inherits from is also called.

So if you have the following classes:

public class Base { }
public class Something : Base { }
public class Else : Something { }

then a constructor in Else, will call a constructor in Something, which will also call a constructor in Base.

The constructor called in a base class (ie. the one you're descending from) is always the parameterless constructor.

If you don't have one, or want to override that, you can override it, by specifying base(some parameters here). This will pick the right constructor in the base class.

You can also ask a constructor to first call another constructor in the same class, at the same level. This can be used to avoid duplicating constructor code in multiple constructors. Ultimately though, the constructors being called will call a constructor in the base class.

I hope this was understandable.



回答5:

Exactly. The call it Constructor Chaining and it's used to get around the fact that C# doesn't have the ability to do default arguments.

This is used a lot in IoC.



回答6:

It's like this if i'm not mistaken:

public MyClass(SomeArg arg) : this(new SomethingElse(), arg)

will call

public MyClass(SomethingElse arg, SomeArg arg1) : base or this or nothing

and that will go on until you got a base or nothing.

If you have base(....) then that constructor having that will call the base constructor with the parameters (if any) given, which in turn can delegate to its own constructors (same game).

If you have nothing, then the parameter-less constructor of the base-class is called automatically.

After you have used this(....), then the constructor matching the parameters will be used and its body will be executed - additionally to the body of the constructor having used this(....).



回答7:

Yes you are right. This syntax is used to have your subclass constructors to explicitly call an appropriate custom base class constructor, rather than the default. The this keyword in your question is explained:

Another use of the this keyword is to force one constructor to call another in order to avoid redundant member initialization logic.

in Pro C# 2005 and the .NET 2.0 Platform, 3rd Edition by Andrew Troelsen