Название | Professional C# 6 and .NET Core 1.0 |
---|---|
Автор произведения | Christian Nagel |
Жанр | Зарубежная образовательная литература |
Серия | |
Издательство | Зарубежная образовательная литература |
Год выпуска | 0 |
isbn | 9781119096634 |
NOTE Microsoft teams use either one or the other naming convention. For using private members of types,NET doesn’t have strict naming conventions. However, within a team the same convention should be used. The .NET Core team switched to using an underscore to prefix fields, which is the convention used in this book in most places (see https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md).
Auto-Implemented Properties
If there isn’t going to be any logic in the properties set and get, then auto-implemented properties can be used. Auto-implemented properties implement the backing member variable automatically. The code for the earlier Age example would look like this:
The declaration of a private field is not needed. The compiler creates this automatically. With auto-implemented properties, you cannot access the field directly as you don’t know the name the compiler generates.
By using auto-implemented properties, validation of the property cannot be done at the property set. Therefore, with the Age property you could not have checked to see if an invalid age is set.
Auto-implemented properties can be initialized using a property initializer:
Access Modifiers for Properties
C# allows the set and get accessors to have differing access modifiers. This would allow a property to have a public get and a private or protected set. This can help control how or when a property can be set. In the following code example, notice that the set has a private access modifier but the get does not. In this case, the get takes the access level of the property. One of the accessors must follow the access level of the property. A compile error is generated if the get accessor has the protected access level associated with it because that would make both accessors have a different access level from the property.
Different access levels can also be set with auto-implemented properties:
NOTE You can also define properties that only have a get or set accessor. Before creating a property with only a set accessor, it’s a good practice to create a method instead. You can use properties with only a get accessor for read-only access. Auto-implemented properties with only get accessors are new with C# 6 and discussed in the section “Readonly Members.”
NOTE Some developers may be concerned that the previous sections have presented a number of situations in which standard C# coding practices have led to very small functions – for example, accessing a field via a property instead of directly. Will this hurt performance because of the overhead of the extra function call? The answer is no. There’s no need to worry about performance loss from these kinds of programming methodologies in C#. Recall that C# code is compiled to IL, then JIT compiled at runtime to native executable code. The JIT compiler is designed to generate highly optimized code and will ruthlessly inline code as appropriate (in other words, it replaces function calls with inline code). A method or property whose implementation simply calls another method or returns a field will almost certainly be inlined.
Usually you do not need to change the inlining behavior, but you have some control to inform the compiler about inlining. Using the attribute MethodImpl, you can define that a method should not be inlined (MethodImplOptions.NoInlining), or inlining should be done aggressively by the compiler (MethodImplOptions.AggressiveInlining). With properties, you need to apply this attribute directly to the get and set accessors. Attributes are explained in detail in Chapter 16, “Reflection, Metadata, and Dynamic Programming.”
Methods
Note that official C# terminology makes a distinction between functions and methods. In C# terminology, the term “function member” includes not only methods, but also other nondata members of a class or struct. This includes indexers, operators, constructors, destructors, and – perhaps somewhat surprisingly – properties. These are contrasted with data members: fields, constants, and events.
Declaring Methods
In C#, the definition of a method consists of any method modifiers (such as the method’s accessibility), followed by the type of the return value, followed by the name of the method, followed by a list of input arguments enclosed in parentheses, followed by the body of the method enclosed in curly braces:
Each parameter consists of the name of the type of the parameter, and the name by which it can be referenced in the body of the method. Also, if the method returns a value, a return statement must be used with the return value to indicate each exit point, as shown in this example:
If the method doesn’t return anything, specify a return type of void because you can’t omit the return type altogether; and if it takes no arguments, you still need to include an empty set of parentheses after the method name. In this case, including a return statement is optional – the method returns automatically when the closing curly brace is reached.
Expression-Bodied Methods
If the implementation of a method consists just of one statement, C# 6 gives a simplified syntax to method definitions: expression-bodied methods. You don’t need to write curly brackets and the return keyword with the new syntax. The operator => (the lambda operator) is used to distinguish the declaration of the left side of this operator to the implementation that is on the right side.
The following example is the same method as before, IsSquare, implemented using the expression-bodied method syntax. The right side of the lambda operator defines the implementation of the method. Curly brackets and a return statement are not needed. What’s returned is the result of the statement, and the result needs to be of the same type as the method declared on the left side, which is a bool in this code snippet:
Invoking Methods
The following example illustrates the syntax for definition and instantiation of classes, and definition and invocation of methods. The class Math defines instance and static members (code file MathSample/Math.cs):
The Program class makes use of the Math class, calls static methods, and instantiates an object to invoke instance members (code file MathSample/Program.cs);
Running the MathSample example produces the following results:
As you can see from the code, the Math class contains a property that contains a number, as well as a method to find the square of this number. It also contains two static methods: one to return the value of pi and one to find the square of the number passed in as a parameter.
Some features of this class are not really good examples of C# program design. For example, GetPi would usually be implemented as a const field, but following good design would mean using some concepts that have not yet been introduced.
Method Overloading
C# supports method overloading – several versions of the method that have different signatures (that is, the same name but a different number of parameters and/or different parameter data types). To overload methods, simply declare the methods with the same name but different numbers of parameter types:
It’s