✅ Nested classes in C# with parent being a generic class
Hello guys, consider the code in the picture, can someone explain why the type parameters declared in our parent generic class is available in the nested private class please.
Also notice in the following code:
We declare a private class with parentheses, what does that implies please.

62 Replies
Type parameters of the parent are available to the children
The same way
is possible without giving
Bar
a type parameter, so is
In addition, the parenthesis are unrelated to type parameters, that's a primary constructor
Declare and use C# primary constructors in classes and structs
Learn how and when to declare primary constructors in your class and struct types. Primary constructors provide concise syntax to declare constructor parameters available anywhere in your type.
Hmm I think I still have some confusion on generic, can you just confirm the following pls:
Here we declare a generic class. We are using a function name Bar with parameter T (T is same type as in class definition) and that function is returning
thing
which has the same data type as the class Foo, that is T.
Now consider second piece of code. I understood that Bar is kind of "inheriting" the type of Foo, that is T. Does that mean T becomes a field of Bar? or we can just use it as a property? Also, is there a reason why we would prefer to use the idea of nested classes?
ahh didn't know about that, I just had a look, from what I've understand, it's just a shorter way to define constructors?Effectively
And it answers the second part of your question there
hmm the idea of why we use nested classes?
No, the stuff about what does T become
I was just reading a bit, so, from what I've understand, when we define the generic type parameter in the outer class definition, the inner class, private is inheriting that field also, so we do have a data type Thing here for e.g. Now the "Thing" variable, is it available for both the class Foo and Bar or only for Bar?
yeah I see, in fact, T does become a field or Bar, right ?
T becomes nothing. It's just a type parameter
t (note the lowercase) is a field of Bar, of type T
yeah sorry, I mean t, yep, so t is the field of both Bar and Foo or only that of Bar ?
t
is a primary constructor parameter of Barah I see, is it correct to say the following:
in the above code, the outer class is a generic class with type parameter T. Normally, this mean this class can have a single instance variable of type T.
Now, when we define the inner private class, that inner private class kind of inherit the T generic parameter from the outer class meaning that we can also define an instance variable with type T. In this case, this is represented by small letter t
Normally, this mean this class can have a single instance variable of type T.Not sure where you got this impression, but no
333fred
REPL Result: Success
Console Output
Compile: 503.698ms | Execution: 68.940ms | React with ❌ to remove this embed.
ah ok, we can define as many instanve variable of type T as we want?
Within some limit set by the runtime, but effectively yes
If you need more than it allows, you need to ask yourself what the hell you're doing 😄
yep I see
beside that, was there any missconception of what I said afterwards pls
You're pretty close. I could make some quibbles about calling
t
an "instance variable", but that's to do with primary constructors, not with genericsgive your feedback !! else I would do the same error next time :c
As I said earlier,
t
isn't an instance variable. It's a primary constructor parameterah
but normally, when we pass t in the primary constructor, basically it should have a field, no? so if for example in a class of Person, I use string name in a primary constructor, this mean behind the scene I have a field of name ?
No, it doesn't mean that
You may get a backing field if you actually capture the parameter
But in your example,
t
is not captured, so there is no field backing t
. Instead, your property Data
has a backing fieldahhhh
I see
this is what you mean by captured, like we are creating a property
ok ok, starts to make sense, so t is a primary constructor noted yep
See what code gets generated for each of those
2sec
everytime there is a backing field, we have the wordings __BackingField when viewed in sharpLab?
The compiler chooses a name
Just look at what the members are, not at their names
The compiler can use whatever name it wants
No
{ get; set; }
? It's a field
But, generally, yeah2sec
(That being said, if we changed the pattern we use for generating backing fields, we'd probably break the world...)
Let's consider one by one, what I understand from the class Foo, is that it doesn't have the backing field

it just have the primary constructor
Correct
now what I understand from the class Bar, it does have a field, the private int _x thing
Also correct, but this isn't a backing field. It's a manually-declared field
yep
2sec 2 more left
You just know someone does some weird shenanigans with Roslyn and regexing for
_BackingField
:KEKW:This one now

I noticed that private int <x>P is before the constructor of Quz
this mean it is a field also ?
Order doesn't actually matter: it just is a field because it looks like a field
ahh
I see
but why did that get generated? because we don't have any field declared in the class, just a non-static method I think
That got generated because
Quz.Foo
captured the primary constructor parameterahh
Every time you invoke that method, it needs to run
x * 2
So it needs to know what x
isyep
last one
That's capturing
2sec
ohh
wait last one then we will reflect on what happen

here it is, the magic word
The last one is most representative of what you originally wrote
"BackingField" !!!!
so here, normally it has a backing field right? but their is no capture ? because here when we assign t to the property, their was no capture
Right. When you assign
t
to the property, that runs as part of the constructor
So nothing needs to be capturedyep start to make sense, 2min I will just refresh and come back with some question/ a summary
small question

in the last class Baz, notice that we have a backingField, but not for x right but for X ?
Precisely
alright, sooo from what I've understood (please correct me if I'm wrong):
what we mean by "capture" is that, we want a particular variable to "persist". for example, in the example you gave, in the second class Node, we know that the method Data will always return t (when the primary constructor is called, t is passed as argument but then later on, if we need to modify data, how would we do it if t doesn't exist, so t is captured.)
In the first class of node though, in the property Data, we set the value of Data to t; the value of Data is set only once, during instantiation; then we don't bother about what t is, so t is discarded (not captured) ?
Yup
Thanks !! I believe I now have a clearer understanding how all that works behind the scenes; I can close the post now 😂 thanks too @Angius 💯