Generics used in struct vs class
Solution 1
That is because a compiler rule enforces that all fields in a struct must be assigned before control leaves any constructor.
You can get your code working by doing this:
public Foo(T first)
{
this.First = first;
this.Second = default(T);
}
Also see Why Must I Initialize All Fields in my C# struct with a Non-Default Constructor?
Solution 2
That's a requirement of structs in general -- it has nothing to do with generics. Your constructor must assign a value to all fields.
Note the same error happens here:
struct Foo
{
public int A;
public int B;
public Foo()
{
A = 1;
}
}
Solution 3
Because it is a rule in C# that all fields must be assigned for structs (inline or in constructor). This is because of a struct nature. It has nothing about generic it or not generic.
Sleiman Jneidi
I am lexically scoped. #SOreadytoHelp Read More, Recursively!!
Updated on November 21, 2021Comments
-
Sleiman Jneidi over 2 years
Assume that we have the following
struct
definition that uses generics:public struct Foo<T> { public T First; public T Second; public Foo(T first) { this.First = first; } }
The compiler says
'Foo.Second' must be fully assigned before control is returned to the caller
However, if
Foo
is a class, then it compiles successfully.public class Foo<T> { public T First; public T Second; public Foo(T first) { this.First = first; } }
Why? Why the compiler treats them differently? Moreover if no constructor is defined in the first
Foo
then it compiles. Why this behaviour? -
Buh Buh over 11 yearsThat's not right. In classes all fields are initialized to their default values, regardless of what you do. If you set a field to null then you are setting it twice.
-
Jeff over 11 years@BuhBuh Oh, right you are. Getting my languages mixed up terribly :(
-
supercat over 11 yearsIt's interesting to note that the C# rule is essentially unenforceable, since .net doesn't have real "out" parameters. C# may expect that any parameter with an
Out()
attribute will be written, but nothing in the CLS spec justifies any such assumption when calling external functions. If a virtual method with anout
parameter is overridden in a language which doesn't know about theOut()
attribute, that language will regard the parameter as aref
parameter which the override method may write or not as it sees fit. It's worth noting thatvar it = new StructType(params);
does not... -
supercat over 11 years...always get performed by creating a temp instance and then copying to
it
; the compiler may simply have the constructor mutate the fields of the existingit
instance directly. It may assume that all fields will be written before being read, but in reality there's no guarantee that any of them will be written. -
driis about 10 years@BillW why is that ? It succinctly show the OP what he could do to get his sample to compile.
-
ToolmakerSteve over 2 yearsBTW: This would be an answer to the second part if the second part had been asking about a class. OP actually asked why a struct ("the first foo") is valid without any constructor definition. The correct answer for a struct is "a struct always has an implicit parameterless constructor." In c#, there is no way to "disallow"
new MyStruct()
. That always is valid. In fact, for a struct, you can't even declare your own parameterless constructor, to override the default behavior! -
Jeff over 2 years@ToolmakerSteve thanks! I've updated the answer - if you get a moment it'd be great to get your eyes across to make sure I haven't loaded in any more misinformation - it's been a few years since I was an active coder!