Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

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>
https: //www. youtube. com/watch? v=J9Cwi45UtZU

JeremyBytes - C# Generics - Part 2: Interfaces: A look at how Generic types can be used in the creation of interfaces.
https: //www. youtube. com/watch? v=DhStyoxuWnE

JeremyBytes - C# Generics - Part 3: Methods & Delegates: A brief overview of how Delegates like Func< TSource, TKey> and Action< T> implement Generics
https: //www. youtube. com/watch? v=PrQumlfBZVw

JeremyBytes - C# Generics - Part 4: Nested Generics: A look at how Generics can be nested within one another
https: //www. youtube. com/watch? v=Kj3DkUrtI7c

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
https: //www. youtube. com/watch? v=oitvN9YC_PU

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:
public virtual void Start() {

header. text = Locale. Translate(lineItemData. myText);

}

In the Child Class: Mark the method as override with a public accessor:
public override void Start() {

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:
public abstract string saveKey { get; set; }

In the Child Class:
public override string saveKey { get => InfoGraphKeys. Budget; set { } }

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:
Public static class ExtensionClassName { }

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:
Public static returnType ExtensionMethod< T> (parameters)

Add this to the First Parameter: The first parameter of the extension method should have the this keyword in front of it:
ExtensionMethod< T> (this FirstType< T> inputVar, SecondType inputVar2)

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:
Using ExtensionClassName;

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:
ExtensionClassName. ExtensionMethod(object, secondParameter);

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. ExtensionMethod(secondParameter);

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:
https: //www. youtube. com/watch? v=v6Zb0nD7PHA

○ 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:
https: //www. youtube. com/watch? v=0qnwc5XqVs0

○ Get Func-y: Delegates in. NET - Jeremy Clark: A combination lecture of the above 3 parts
https: //www. youtube. com/watch? v=cQ5qF9PmyCQ

○ C# in Depth: Delegates and Events: Contains a little more information about delegates and how they work together with Events
https: //csharpindepth. com/articles/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:
Public delegate returnType DelegateTypeName(ClassAType inputVar);
deligateInstance = DelegateTypeName;

DelegateTypeName represents a type (delegate type).
A delegate “type” is the definition which holds the Method Signature (the return type and parameter list type)

deligateInstance holds a reference to the delegate type, and is an instance of a delegate type.
A delegate “instance” is an instance of a delegate type which holds a reference (or references) to 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:
Public delegate returnType DelegateTypeName(ClassAType inputVar);

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:
Public returnType MethodName(DelegateTypeName inputDelegate) {
return inputDelegate. Invoke(this);
}

■ 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:
return inputDelegate(this);

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:
Public returnType MethodName(DelegateTypeName inputDelegate) {
if (inputDelegate! = null)
      return inputDelegate(this);
return somethingElse;
}

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,
Public returnType ClassBMethodName(OriginalClassType inputDelegate) {
return returnType;

}

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:
ClassAType oct;
oct. MethodName(ClassBMethodName);

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:
DelegateTypeName delegateHoldingVariable;
delegateInstance = ClassBMethodName;
ClassAType oct;
oct. MethodName(delegateInstance);

■ 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:
delegateVarName = ClassC. MethodCName;

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 = delegate(delegateParameters) {
delegateDefinition;
};

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).
Public delegate string PersonFormatter( Person input);

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:
Func< Person, string >

Replacing in Methods: In the case of the previous example, where previously we would have had a method defined as:
Public string ToString(PersonFormatter inputVar) {}

■ We replace PersonFormatter with an equivalent Func:
Public string ToString(Func< Person, string > inputVar) {}

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:
DelegateTypeName delegateHoldingVariable;

■ We replace DelegateTypeName with an equivalent Func:
Func< Person, string > delegateHoldingVariable;

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.
https: //youtu. be/cQ5qF9PmyCQ? t=3320

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).
Public delegate void PersonFormatter( Person input);

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:
Action< Person >

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:
delegateHoldingVariable += MethodToSubscribeTo;

Long-form combining: The above syntax is equivalent to:
dHVariable = dHVariable + MethodToSubscribeTo;

Delegate. Combine(a, b): Delegates can also be combined using the static method “Delegate. Combine”
dHVariable = Delegate. Combine(dHVariable, MethodToSubscribeTo);

Delegate. Combine(delegate[]): To combine more than one delegate at a time, the Combine method can also take an array of delegates:
dHVariable = Delegate. Combine( {delegate1, delegate2, delegate3, etc. });

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 += MethodToSubscribeToA;

delegateHoldingVariable += MethodToSubscribeToB;
delegateHoldingVariable();

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:
delegateHoldingVariable -= MethodToUnsubscribeFrom;

Long-form removal: The above syntax is equivalent to:
dHVariable = dHVariable - MethodToUnsubscribeFrom;

Delegate. Remove(a, b): A method can be removed from a delegate with the static Remove method
https: //docs. microsoft. com/en-us/dotnet/api/system. delegate. remove? view=netframework-4. 8

First in, last out: Unsubscribing from a delegate removes the last occurrence of it from the “stack”
delegateHoldingVariable += MethodToSubscribeTo A;

delegateHoldingVariable += MethodToSubscribeTo B;

delegateHoldingVariable += MethodToSubscribeTo A;
//delegateHoldingVariable contains “A B A”
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.
https: //docs. microsoft. com/en-us/dotnet/api/system. delegate. removeall? view=netframework-4. 8

Clear Subscriptions with Null: To clear the list of methods the delegate holds reference to, it can be assigned a value of null:
delegateHoldingVariable = 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:
if (delegateHoldingVariable! = null)
       delegateHoldingVariable();

Alternate syntax: The above statement can also be written as:
delegateHoldingVariable? Invoke();

■ 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
https: //docs. microsoft. com/en-us/dotnet/api/system. delegate. getinvocationlist? view=netframework-4. 8

DynamicInvoke () takes an array of objects that are the arguments to pass to the method represented by the current delegate
https: //docs. microsoft. com/en-us/dotnet/api/system. delegate. dynamicinvoke? view=netframework-4. 8

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 Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...