C Generic Parameter Conversion
- 2021-12-04 19:28:16
- OfStack
The objects generated by different parameter types of generics are independent of each other.
// Such as
Tuple<string> ts;
Tuple<object> to;
//ts to Are two types of objects.
Many times, we want to implement to = ts. Why? Because it seems that it should be.
To achieve this goal, we need to solve the "generic parameter conversion problem", and the knowledge point of this problem is in out generic variant. To be honest, the problem itself is not difficult, but it is very intuitive and easy to forget.
First of all, in order to implement to = ts, there is actually a premise, that is, this parameter can only be used on "return type".
// Such as
delegate object FuncObj();
FuncObj func = ()=>"string";
func is successful because string can be converted into object. When the "user" calls func, he wants an object object, and string is also an object object, so there is no problem.
The key here is to learn to analyze problems from the perspective of "users".
//A
delegate void FuncObj2(object obj);
FuncObj2 func2 = (string str)=>{};
//B
delegate void FuncStr(string str);
FuncStr func3 = (object obj)=>{};
Analyze these two sets of codes, which one is more reasonable?
From the user's point of view, it uses func2 and func3
When the user uses func2, the object passed must be object, but the actual function processed is (string) = > {}, object cannot be converted to string, so it is very unreasonable.
When the user uses func3, the object passed can only be string, and the actual function processed is (object) = > {}, string can be converted to object, so it is reasonable.
Of course, these two sets of codes are not valid because the function parameter types do not match.
However, generics provide a method to implicitly convert objects with mismatched types! The logic of its implementation is analyzed above.
//out Modify return type
delegate ResultType FuncOut<out ResultType>();
//in Modify parameter type
delegate void FuncIn<in ParamType>(ParamType param);
// This is 1 Start what we want to achieve
FuncOut<object> fun4 = () => "string";
// This effect is just the opposite
FuncIn<object> funcobj = (object obj) => { };
FuncIn<string> fun5 = funcobj;
// Note that generic variants 1 You can only implicitly convert between generic variants and generic variants
//lambda Expressions are automatically converted to generic variants with the same parameters, but implicit conversion between variants cannot be followed, so you need to funcobj To transition
out modifies the return type and in modifies the parameter type, which is quite vivid, but note that the generic in parameter is the opposite of the out parameter.
At first, we wanted to implement to = ts, but we only saw the first half of the problem. In fact, generics have the possibility of ts = to. I hope readers can understand this point.
Summary:
out : to = ts;
in : ts = to;
No modification: to and ts are completely independent.
----(Remarks)------------------------------------------------------------------------------------------------------------------
out parameter: Can only be used with return types.
in Parameter: Can only be used on parameters.
Undecorated: Anywhere.
-----(Note 2)----------
in, out generic parameters can only be used on delegates and interfaces.
// Comprehensive application
delegate ResultType FuncInOut<in ParamType, out ResultType>(ParamType param);
FuncInOut<object, string> funcobj2 = (object obj) => "string";
FuncInOut<string, object> func6 = funcobj2;