Professional C# 6 and .NET Core 1.0. Christian Nagel

Чтение книги онлайн.

Читать онлайн книгу Professional C# 6 and .NET Core 1.0 - Christian Nagel страница 30

Professional C# 6 and .NET Core 1.0 - Christian Nagel

Скачать книгу

idea of a property is that it is a method or a pair of methods dressed to look like a field. Let’s change the field for the first name from the previous example to a private field with the variable name _firstName. The property named FirstName contains a get and set accessor to retrieve and set the value of the backing field:

      The get accessor takes no parameters and must return the same type as the declared property. You should not specify any explicit parameters for the set accessor either, but the compiler assumes it takes one parameter, which is of the same type again, and which is referred to as value.

      Let’s get into another example with a different naming convention. The following code contains a property called Age, which sets a field called age. In this example, age is referred to as the backing variable for the property Age:

      Note the naming convention used here. You take advantage of C#’s case sensitivity by using the same name – Pascal-case for the public property, and camel-case for the equivalent private field if there is one. In earlier .NET versions, this naming convention was preferred by Microsoft’s C# team. Recently they switched to the naming convention to prefix field names by an underscore. This provides an extremely convenient way to identify fields in contrast to local variables.

      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

Скачать книгу