C
C#3w ago
Faker

✅ What is the syntax for generics in methods signature

Hello guys, consider the following: TraverseBreadthFirst<T>(T, Func<T, IEnumerable<T>>) Declaration: public static IEnumerable<T> TraverseBreadthFirst<T>(T root, Func<T, IEnumerable<T>> childrenSelector) Can someone explain what T refers to please, is it the return type or the type that the argument can take? I'm always confuse by that... what if we can have multiple generic parameters? How would we represent them? Is there a syntax to follow? for example in the Func<T, IEnumerable<T>> delegate type, I know that T is the argument and IEnumerable<T>> is the return type
15 Replies
Jimmacle
Jimmacle3w ago
T is a type parameter, it can be either or both of the things you said it basically lets you replace anywhere there's a T in the method with your own type when you call it
Faker
FakerOP3w ago
oh ok, irrespective whether it's a return type or argument, whatever we pass as our first argument, will represent the generic type ? we can add more generic types by using something like public static IEnumerable<T> TraverseBreadthFirst<T,X>(T root, X justAVariable , Func<T, IEnumerable<T>> childrenSelector) ?
FusedQyou
FusedQyou3w ago
You can't dynamically change the type if that's what you mean And yes, you can. Can't say what the limit is, though
Jimmacle
Jimmacle3w ago
you can have multiple type parameters like <T1, T2, T3, ...>
FusedQyou
FusedQyou3w ago
The whole idea of a generic is so a common type can be used in a method without having to rely on that common type statically and instead you can just specify it yourself. Like here your collection You can also specify a type that is not common, but does have a rule. For example, must not be null, or it must be a class/struct
Jimmacle
Jimmacle3w ago
(they also don't have to be called T, that's just convention)
ero
ero3w ago
the compiler just happens to be able to infer the type in some cases
FusedQyou
FusedQyou3w ago
One less important thing is also that it avoids boxing, if you care about that (or less important to most that is)
MODiX
MODiX3w ago
ero
REPL Result: Success
void M<T>(T arg) { }

int i = 0;
M(i);
M<int>(i);
void M<T>(T arg) { }

int i = 0;
M(i);
M<int>(i);
Compile: 326.853ms | Execution: 28.102ms | React with ❌ to remove this embed.
ero
ero3w ago
both M(i) and M<int>(i) are valid here, because the compiler can infer that T is int in the first case
MODiX
MODiX3w ago
ero
REPL Result: Failure
void M<T>() { }

M();
void M<T>() { }

M();
Exception: CompilationErrorException
- The type arguments for method 'M<T>()' cannot be inferred from the usage. Try specifying the type arguments explicitly.
- The type arguments for method 'M<T>()' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Compile: 274.814ms | Execution: 0.000ms | React with ❌ to remove this embed.
ero
ero3w ago
this can never be valid, because the compiler can't know what T is
Faker
FakerOP3w ago
oh ok, so in some cases, we can just write M(i) instead of M<int>(i) ?
Jimmacle
Jimmacle3w ago
yes, if the compiler can infer the type you don't need to specify it yourself
Faker
FakerOP3w ago
Alright noted, it's clearer now, thanks guys !!

Did you find this page helpful?