Followup to this question: Why is Nullable<T> considered a struct and not a class?
I have two classes that essentially maintain a tuple of some user-supplied value with an internal object.
When the type of the user-supplied value is a primitive, I have to wrap it in a Nullable<T>
so that it can take on a null value in the Tuple.
public class BundledClass<T> where T : class
{
private Tuple<T, object> _bundle;
public T Value
{
get { return _bundle == null ? null : _bundle.Item1; }
set { _bundle = new Tuple<T, object>(value, internalObj); }
}
//...
public class BundledPrimitive<T> where T : struct
{
private Tuple<T?, object> _bundle;
public T? Value
{
get { return _bundle == null ? null : _bundle.Item1; }
set { _bundle = new Tuple<T?, object>(value, internalObj); }
}
//...
I'd prefer it if I could do this with a single class that can take either primitives or classes as a type parameter, but I don't see any way around it. Not without coming up with some sort of custom Nullable
class that can box any type (not just types where T:struct
) so as to ensure that Value
can always be assigned null;
It seems like I should at least be able to define the latter class as
public class BundledPrimitive<T> : BundledClass<T?> { }
But even that fails since Nullable<T>
does not meet the : class
constraint (as per the linked question).
If you simply designed your class like this:
Then you can use it with a struct by specifying the type parameter as a
Nullable<T>
, for example:The only problem here is that it's possible that a user could use this class with a non-nullable struct—e.g.
Bundled<int>
. If that's really a concern in your application, you could declare more specific sub-types like this:You also can make the constructor for
Bundled<T>
internal so it can't be called from outside your assembly. This will ensure that the user doesn't create a custom sub-type to bypass yourBundledClass
/BundledStruct
wrappers.