This question has already been answered:
Why are the parameters T1 , T2 , ... are contravariant ( in T1 , in T2 , ...) in Action ?
And why is the return type in Func is out TResult ?
This question has already been answered:
Why are the parameters T1 , T2 , ... are contravariant ( in T1 , in T2 , ...) in Action ?
And why is the return type in Func is out TResult ?
A similar question was asked earlier and an answer has already been received. If the answers provided are not exhaustive, please ask a new question .
On the fingers: if you need a hairdresser for dogs ( Action<Dog> ), a universal hairdresser for animals (a function that accepts Animal input) is suitable.
Therefore, an Action<Dog> variable can be assigned an Action<Animal> expression.
On the contrary, if you need to get any kind of animal ( Func<Animal> ), then the kitty shop is suitable ( Func<Kitten> ).
Therefore, a variable of type Func<Animal> can be assigned an expression of type Func<Kitten> .
In more detail: What is the essence of the covariance and contravariance of delegates? Contravariance of generalized C # delegates .
Action delegates are countervariant because where you can use an instance of an ancestor class, you can also use an instance of a descendant in the same place. Example:
Action<string> act1 = str => { int i = str.Length; }; Action<object> act2 = o => { string s = o.ToString(); }; // вы можете сделать такое присваивание act1 = act2; // и затем вызвать делегат вот так, // потому что по факту у вас будет вызван 2-ой делегат, // которому будет передана string, производная от object act1("10"); Since string is a descendant of object , you can do the same with this parameter as with object . There is no error. However, you can not do this:
act2 = act1; Because in this case, you could pass some object to a method that actually requires a string , and this is already an error.
Covariance of Func is similarly explained:
Func<string> func1 = () => "str"; Func<object> func2 = () => 10; // такое присваивание тоже возможно func2 = func1; // ваш делегат вернёт некий object, который по факту является строкой. object r = func2(); Similar to the previous example, you can not do this:
func1 = func2; since in this case the delegate that returns a string , you can assign a delegate that returns an object (which in our example is actually of type int ).
Source: https://ru.stackoverflow.com/questions/748116/
All Articles