Generics. Inheritance. StringBuilder. Lazy Evaluation. Extension Methods. Delegates
Generics ● Reference: ○ JeremyBytes - C# Generics - Part 1: Collections: A look at the use of Generics in familiar objects like List< T> ○ JeremyBytes - C# Generics - Part 2: Interfaces: A look at how Generic types can be used in the creation of interfaces. ○ JeremyBytes - C# Generics - Part 3: Methods & Delegates: A brief overview of how Delegates like Func< TSource, TKey> and Action< T> implement Generics ○ JeremyBytes - C# Generics - Part 4: Nested Generics: A look at how Generics can be nested within one another ○ JeremyBytes - C# Generics - Part 5: Generic Constraints & " default": Using Constraints limits what T is allowed to be while default can help gain back some flexibility ● Strongly Typed vs “Not Strongly Typed”: Inheritance ● Overriding Methods in Child Classes: ○ In the Parent Class: Mark the method as virtual with a public accessor: header. text = Locale. Translate(lineItemData. myText); } ○ In the Child Class: Mark the method as override with a public accessor: base. Start(); city = DI. Get< City> (); } ■ base. Start() calls the code written in the parent Method ● Overriding Properties in Child Classes: You cannot truly override a field in a child class, only hide it. ○ In the Parent Class: ○ In the Child Class: https: //stackoverflow. com/questions/326223/overriding-fields-or-properties-in-subclasses StringBuilder Lists https: //docs. microsoft. com/en-us/dotnet/api/system. collections. generic. list-1? view=netframework-4. 8 ● Shuffle a List: Randomize a List< T> Lazy Evaluation ● LINQ methods are not applying a filter until they are used Extension Methods ● PREREQUISITE (Static Classes, Generics) ● Reference: ○ JeremyBytesExtension Methods in C#: https: //www. youtube. com/watch? v=fKxy8Hl7Ht0 ○ Microsoft Documentation: https: //docs. microsoft. com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods ● Usage: ○ Extend Classes: Extension methods enable you to " add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. ■ Add new methods to an existing class (even one you can’t access directly) ○ Extend MULTIPLE methods: You can create new static methods which extend the functionality of not just one, but any number of classes.
○ LINQ: LINQ is a library of Extension Methods, and a great example of Extension Methods in action ● Implementation: ○ Stored in a Static Class: ○ Methods are Static with Generics: Naturally, being in a Static Class, the Extension methods themselves are also static. The method makes use of Generics and returns whatever type you require: ○ Add this to the First Parameter: The first parameter of the extension method should have the this keyword in front of it: ■ FirstType< T> can be an Interface such as IEnnumerable so that any class which implements IEnnumerable can go in its place. ○ Include the using directive: At the top of whichever class you intend to use the Extension Method, include a using directive to the name of the static extension class: ○ Expected usage: Not really taking advantage of the “Extension Method” you can use the static method from our Static class exactly as you’d expect: ■ Object refers to an object of a particular class type which we are passing in as the initial parameter to our extension method. ■ SecondParameter is simply any other parameter we are passing to the method, additional parameters would be passed in in similar fashion. ○ Extension Method usage: We can omit the reference to the ExtensionClassName and pass the first parameter to our Extension Method implicitly through the following invocation: ■ Object is now implicity is passed along through usage of the “this” keyword” in place of the first parameter. The Extension Method now truly appears as though it were a method of the object class. Delegates ● PREREQUISITE (Method Signatures, Static vs Non-Static Methods, Generics): ○ Method Signatures: Delegates are all about matching Method signatures to be able to pass them around, so it is vitally important to know what a Method signature is before you can properly understand delegates. ○ Static vs Non-Static Methods: You can use a Static class to implement a number of delegate methods. ○ Generics: Built-in Delegates Func< T> and Action< T> make use of Generic types ● Section Reference: ○ JeremyBytes - C# Delegates - Part 1: Basics: A 3 part series which is an excellent introduction to Delegates: ○ JeremyBytes - C# Delegates - Part 2: Getting Func-y (+ Lambdas): https: //www. youtube. com/watch? v=0nd-tcQcslc ○ JeremyBytes - C# Delegates - Part 3: Action & Multicast Delegates: ○ Get Func-y: Delegates in. NET - Jeremy Clark: A combination lecture of the above 3 parts ○ C# in Depth: Delegates and Events: Contains a little more information about delegates and how they work together with Events
● A custom Type that defines a method Signature: “Higher order” functions which take other functions as parameters (Functional Programming) ● Why is it called a delegate?: A delegate is so-called because it can be used to “delegate” the responsibility of a method’s execution. ● Confusion surrounding the term: “Another source of confusion is the overloading of the term " delegate". Sometimes it is used to mean a delegate type, and at other times it can be used to mean an instance of a delegate type” Below is an example of the difference between a delegate type and an instance of a delegate type: ○ DelegateTypeName represents a type (delegate type). ○ deligateInstance holds a reference to the delegate type, and is an instance of a delegate type. ● Uses: ○ Decoupling Code: ■ Pass Methods as Parameters: Delegates allow you to pass a Method as a parameter to another Method ■ Define the behaviour of one class in a different class: A method signature defined can be defined in any other class as long as they adhere to the return type and parameters of the method ○ Multicast Capabilities: Multiple methods can be assigned to a single delegate variable. ■ Call one, call all: When the delegate is invoked, all of the assigned methods are run. ○ Callbacks and Event Handlers: ○ LINQ: See section on LINQ for Delegate usage ● Basic Delegate Declaration: ○ Define the Delegate: In “ClassA” we define a publicly accessible delegate: ■ returnType: The expected return type for the delegate ■ DelegateTypeName: The type name used to declare instances of the delegate ■ ClassAType: The type of argument passed to the delegate. In this case, it operates on instances of the same class in which the delegate is defined. There can be any reasonable number of these. ○ Invoke the Delegate: Next, within the class in which the Delegate is defined (ClassA), you can create a method which Invokes the delegate: ■ inputDelegate: Represents a method of type DelegateTypeName which will be passed to this method to be invoked within the body of MethodName ■ Implicit Invocation: Note that Invocation can be done implicitly: ○ Error Handling: It is possible for a null delegate to be passed to our invocation method, so to protect against this, we should verify that the “inputDelegate” is not null: ■ somethingElse simply refers to a default return for the method in the event that inputDelegate was null. Note that it should be something of type “returnType” to be a valid return candidate. ○ Match the Delegate: Now, in a different class (ClassB), you can create a method whose signature matches the Delegate, } ■ ClassBMethodName: Represents a new method defined in a class other than the class in which the original delegate was defined (ClassA). ○ Pass a Method: Finally, a reference to this method can be passed as an argument to the method we call defined in the original class:
■ oct: Represents a reference to an instance of ClassA (the class in which the delegate was defined) ■ MethodName(ClassBMethodName): The method created in “ClassB” is passed as an argument to the original method (which simply invokes the method we pass it) ● A Variable to hold a delegate: ○ https: //youtu. be/cQ5qF9PmyCQ? t=684 ○ Continuing the above example, in ClassB, we can define a variable of type “DelegateTypeName” which will hold references to method signatures. This can be used to pass to our Method call in ClassB: ■ We can assign any method whose signature matches that of the original delegate to the “delegateInstance”, then pass the instance as the argument to “MethodName” ● Defining a Static Class of Methods: ○ https: //youtu. be/cQ5qF9PmyCQ? t=726 ○ We can define a brand new, Static “ClassC” class who holds a number of methods that all match the original signature of the delegate in ClassA. Since ClassC is Static, we can assign methods to “delegateVarName” like so: ○ Or in-line them: An alternative to creating such a class would be to in-line the delegate definitions (see below) ○ Single Responsibility: You may decide to completely avoid keeping ANY methods in ClassB and use ClassC exclusively to contain all the Methods for ClassA. ■ ClassA is the Data ■ ClassB is the Logic ■ ClassC is the Method Library ● Named vs Anonymous Delegates: A delegate with a name is a “named delegate”. Thus far, the delegates described have been “named” delegates. ● Anonymous Delegates: ○ A delegate without a name is referred to as an “anonymous delegate” ○ In-line definition: A delegate without a name can be written with the keyword delegate in place of a given name: ■ delegateInstance is any variable initialized to hold a delegate (reference to a method which takes some input and gives some output) ■ delegateParameters and delegateDefinition are just stand-in filler ■ Completing the in-line definition: Note the tailing semicolon following the set of braces, this is necessary for completing the assignment of the newly created delegate to the delegateInstance ● Func < in T, out TResult> ○ https: //youtu. be/cQ5qF9PmyCQ? t=1094 ○ Replace Custom Delegates with Func: In the above example, “DelegateTypeName” was technically a “custom delegate”, but instead of using a custom delegate, we can use a built-in delegate type “Func” to act in its place. It is essentially acting as a stand-in Method Signature. ○ Advantages of using: ■ Interchangeable: If you create 2 different custom delegates, even if they have the same input / output types (the method signatures match), they cannot be used in place of each other because they are still different types from one another. ■ Tells me what I need: As a bonus, Func displays the input and output of the Delegate, creating a Custom Delegate does not. ○ Func Parameters: Func uses generic Parameters to represent the return type and any number of input types (up to 16) ■ In T: A generic which represents data being passed to the delegate
■ Out TResult: A generic representing the return type ○ Example: The following example represents a delegate which takes in a “Person” Class (which holds data related to a person’s name) and formats it as a string (which is the return type). ○ The Func Equivalent: PersonFormatter is the “custom delegate” we have created, but anywhere we made reference to our Custom Delegate, we simply replace it with the Func statement: ○ Replacing in Methods: In the case of the previous example, where previously we would have had a method defined as: ■ We replace PersonFormatter with an equivalent Func: ■ inputVar represents a parameter name of our delegate which will be used to invoke the delegate in the body of our ToString override. ○ Replacing in Variables: Where you might have created “a variable to hold a delegate” the declaration of this variable can also be substituted with Func: ■ We replace DelegateTypeName with an equivalent Func: ○ Replacing Return Types: Func< > can also be used in place of the return type of a method. For instance, if you were using a Method to assign one of several Methods to a delegate containing variable, rather than assigning to the variable in the body of the method, you can set the return type of the method to use Func< > instead. ○ Func => Lambda: Anywhere Func< > is used essentially represents an opportunity to use anonymous delegates written with lambda expressions ● Action < in T> ○ https: //youtu. be/0qnwc5XqVs0? t=273 ○ Void Delegates: Action< T> is a built-in delegate (like Func) which returns void (it does not have a return type) ○ Action Parameters: Action uses generic Parameters to represent up to 16 input Types ■ In T: A generic which represents data being passed to the delegate ○ Example: The following example represents a delegate which takes in a “Person” Class (which holds data related to a person’s name) and formats it as a string (which is the return type). ○ The Func Equivalent: Usage of Action< > is nearly identical to Func< > except Action< > has no return parameter, so the types of Method Signatures it represents must be void: ○ Multicast Actions: In the way that Func< > represents a great opportunity to use a Lambda expression, Actions are a natural complement for use in Multicasting Delegates, as will be illustrated in the section below: ● MultiCast Delegates: ○ https: //youtu. be/0qnwc5XqVs0? t=347 ○ One variable, many methods: Once you have created a variable to hold a delegate, you can “subscribe” as many delegates to it as you like. ○ Subscribe to a delegate: To subscribe to additional delegates, use the “+=” operator followed by the name of the method you wish to subscribe to: ■ Long-form combining: The above syntax is equivalent to: ■ Delegate. Combine(a, b): Delegates can also be combined using the static method “Delegate. Combine” ■ Delegate. Combine(delegate[]): To combine more than one delegate at a time, the Combine method can also take an array of delegates: https: //docs. microsoft. com/en-us/dotnet/api/system. delegate. combine? view=netframework-4. 8 ○ Invoked In Order: If multiple methods are subscribed to the same delegate, the method are run in the order in which they have been subscribed: delegateHoldingVariable += MethodToSubscribeToB; ■ MethodToSubscribeToA would execute first ■ MethodToSubscribeToB executes second ○ Getting a return value from a multicast delegate: If you try to subscribe to multiple delegates with a return type, only the value of the last delegate which executes will actually be returned when the Multicast delegate is invoked
○ Unsubscribe: To unsubscribe from a delegate, use the “-=” operator followed by the name of the method you wish to unsubscribe to: ■ Long-form removal: The above syntax is equivalent to: ■ Delegate. Remove(a, b): A method can be removed from a delegate with the static Remove method ■ First in, last out: Unsubscribing from a delegate removes the last occurrence of it from the “stack” delegateHoldingVariable += MethodToSubscribeTo B; delegateHoldingVariable += MethodToSubscribeTo A; //delegateHoldingVariable contains “A B” ■ Delegate. RemoveAll(): Removes all occurrences of the invocation list of a delegate from the invocation list of another delegate. ○ Clear Subscriptions with Null: To clear the list of methods the delegate holds reference to, it can be assigned a value of null: ○ Don’t invoke a null delegate: In the event that your Method list is empty, you will get a NullReferenceException error, so it is best to ensure that before you try to check that your delegate is not null before you try to invoke your it: ■ Alternate syntax: The above statement can also be written as: ■ The “? ” in front of the Invoke call verifies that delegateHoldingVariable is not null before invoking it. ○ Run the ones that work: In the above example, if MethodToSubscribeToA were to have an issue of some sort error, then MethodToSubscribeToB would not run because the chain of events has been interrupted. It is possible to mitigate the possibility of complete failure by iterating through the list of methods that exist on the delegate and running each in its own try-catch block through use of the following special delegate methods: ■ GetInvocationList () returns an array of methods in a delegate instance which can be invoked one at a time using an index operator ■ DynamicInvoke () takes an array of objects that are the arguments to pass to the method represented by the current delegate ○ All delegates are multicast delegates: Any delegate instance has the capacity to be a multicast delegate because all delegates derive from “MulticastDelegate” ○ Suggestion: Subscribe to Action, not Func: Since Action< T> delegates do not have a return type, it makes sense to subscribe to any number of them.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|