Professional C# 6 and .NET Core 1.0. Christian Nagel
Читать онлайн книгу.not just the parameter types that can differ; the number of parameters can differ too, as shown in the next example. One overloaded method can invoke another:
NOTE With method overloading, it is not sufficient to only differ overloads by the return type. It’s also not sufficient to differ by parameter names. The number of parameters and/or types needs to difffer.
Named Arguments
Invoking methods, the variable name need not be added to the invocation. However, if you have a method signature like the following to move a rectangle
and you invoke it with the following code snippet, it’s not clear from the invocation what numbers are used for what:
You can change the invocation to make it immediately clear what the numbers mean:
Any method can be invoked using named arguments. You just need to write the name of the variable followed by a colon and the value passed. The compiler gets rid of the name and creates an invocation of the method just like the variable name would not be there – so there’s no difference within the compiled code.
You can also change the order of variables this way, and the compiler rearranges it to the correct order. The real advantage to this is shown in the next section with optional arguments.
Optional Arguments
Parameters can also be optional. You must supply a default value for optional parameters, which must be the last ones defined:
This method can now be invoked using one or two parameters. Passing one parameter, the compiler changes the method call to pass 42 with the second parameter.
NOTE Because the compiler changes methods with optional parameters to pass the default value, the default value should never change with newer versions of the assembly. With a change of the default value in a newer version, if the caller is in a different assembly that is not recompiled, it would have the older default value. That’s why you should have optional parameters only with values that never change. In case the calling method is always recompiled when the default value changes, this is not an issue.
You can define multiple optional parameters, as shown here:
This way, the method can be called using 1, 2, 3, or 4 parameters. The first line of the following code leaves the optional parameters with the values 11, 22, and 33. The second line passes the first three parameters, and the last one has a value of 33:
With multiple optional parameters, the feature of named arguments shines. Using named arguments you can pass any of the optional parameters – for example, this example passes just the last one:
NOTE Pay attention to versioning issues when using optional arguments. One issue is to change default values in newer versions; another issue is to change the number of arguments. It might look tempting to add another optional parameter as it is optional anyway. However, the compiler changes the calling code to fill in all the parameters, and that’s the reason earlier compiled callers fail if another parameter is added later on.
Variable Number of Arguments
Using optional arguments, you can define a variable number of arguments. However, there’s also a different syntax that allows passing a variable number of arguments – and this syntax doesn’t have versioning issues.
Declaring the parameter of type array – the sample code uses an int array – and adding the params keyword, the method can be invoked using any number of int parameters.
NOTE Arrays are explained in detail in Chapter 7, “Arrays and Tuples.”
As the parameter of the method AnyNumberOfArguments is of type int[], you can pass an int array, or because of the params keyword, you can pass one or any number of int values:
If arguments of different types should be passed to methods, you can use an object array:
Now it is possible to use any type calling this method:
If the params keyword is used with multiple parameters that are defined with the method signature, params can be used only once, and it must be the last parameter:
Now that you’ve looked at the many aspects of methods, let’s get into constructors, which are a special kind of methods.
Constructors
The syntax for declaring basic constructors is a method that has the same name as the containing class and that does not have any return type:
It’s not necessary to provide a constructor for your class. We haven’t supplied one for any of the examples so far in this book. In general, if you don’t supply any constructor, the compiler generates a default one behind the scenes. It will be a very basic constructor that initializes all the member fields by zeroing them out (null reference for reference types, zero for numeric data types, and false for bools). Often, that is adequate; if not, you need to write your own constructor.
Constructors follow the same rules for overloading as other methods – that is, you can provide as many overloads to the constructor as you want, provided they are clearly different in signature:
However, if you supply any constructors that take parameters, the compiler does not automatically supply a default one. This is done only if you have not defined any constructors at all. In the following example, because a one-parameter constructor is defined, the compiler assumes that this is the only constructor you want to be available, so it does not implicitly supply any others:
If you now try instantiating a MyNumber object using a no-parameter constructor, you get a compilation error:
Note that it is possible to define constructors as private or protected, so that they are invisible to code in unrelated classes too:
This example hasn’t actually defined any public, or even any protected, constructors for MyNumber. This would actually make it impossible for MyNumber to be instantiated by outside code using the new operator (though you might write a public static property or method in MyNumber that can instantiate the class). This is useful in two situations:
• If your class serves only as a container for some static members or properties, and therefore should never be instantiated. With this scenario, you can declare the class with the modifier static. With this modifier the class can contain only static members and cannot be instantiated.
• If you want the class to only ever be instantiated by calling a static member function (this is the so-called factory pattern approach to object instantiation). An implementation of the Singleton pattern is shown in the following code snippet.
The