I recently came across this Stackoverflow question: When to use struct?
In it, it had an answer that said something a bit profound:
In addition, realize that when a struct implements an interface - as Enumerator does - and is cast to that implemented type, the struct becomes a reference type and is moved to the heap. Internal to the Dictionary class, Enumerator is still a value type. However, as soon as a method calls GetEnumerator(), a reference-type IEnumerator is returned.
Exactly what does this mean?
If I had something like
struct Foo : IFoo
{
public int Foobar;
}
class Bar
{
public IFoo Biz{get; set;} //assume this is Foo
}
...
var b=new Bar();
var f=b.Biz;
f.Foobar=123; //What would happen here
b.Biz.Foobar=567; //would this overwrite the above, or would it have no effect?
b.Biz=new Foo(); //and here!?
What exactly are the detailed semantics of a value-type structure being treated like a reference-type?
A class or struct can implement multiple interfaces, but a class can only inherit from a single class. For more information about abstract classes, see Abstract and Sealed Classes and Class Members. Interfaces can contain instance methods, properties, events, indexers, or any combination of those four member types.
A class or a struct can implement one or more interfaces implicitly or explicitly. Use public modifier when implementing interface implicitly, whereas don't use it in case of explicit implementation. Implement interface explicitly using InterfaceName.
Implementing an interface means to actually write some code to fulfill the description of the interface, in terms of function names, attributes and return values.
Structs and interfaces are Go's way of organizing methods and data handling. Where structs define the fields of an object, like a Person's first and last name. The interfaces define the methods; e.g. formatting and returning a Person's full name.
Every declaration of a structure type really declares two types within the Runtime: a value type, and a heap object type. From the point of view of external code, the heap object type will behave like a class with a fields and methods of the corresponding value type. From the point of view of internal code, the heap type will behave as though it has a field this
of the corresponding value type.
Attempting to cast a value type to a reference type (Object
, ValueType
, Enum
, or any interface type) will generate a new instance of its corresponding heap object type, and return a reference to that new instance. The same thing will happen if one attempts to store a value type into a reference-type storage location, or pass it as a reference-type parameter. Once the value has been converted to a heap object, it will behave--from the point of view of external code--as a heap object.
The only situation in which a value type's implementation of an interface may be used without the value type first being converted to a heap object is when it's passed as a generic type parameter which has the interface type as a constraint. In that particular situation, interface members may be used on the value type instance without its having to be converted to a heap object first.
Read about boxing and unboxing (search the internet). For example MSDN: Boxing and Unboxing (C# Programming Guide).
See also the SO thread Why do we need boxing and unboxing in C#?, and the threads linked to that thread.
Note: It is not so important if you "convert" to a base class of the value type, as in
object obj = new Foo(); // boxing
or "convert" to an implemented interface, as in
IFoo iFoo = new Foo(); // boxing
The only base classes a struct
has, are System.ValueType
and object
(including dynamic
). The base classes of an enum
type are System.Enum
, System.ValueType
, and object
.
A struct can implement any number of interfaces (but it inherits no interfaces from its base classes). An enum type implements IComparable
(non-generic version), IFormattable
, and IConvertible
because the base class System.Enum
implements those three.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With