Click here to Skip to main content
15,868,002 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I realize this question sounds stupid, but please bear with me. I have a class like this:
C#
public class DropDownListViewModel<TScalar>
{
    private bool _valueIsSet;
    private TScalar _value;
    //private Nullable<TScalar> _nullableValue;
    private SelectList _selectList;

    public SelectList SelectList
    {
        get
        {
            return _selectList;
        }
        set
        {
            _selectList = value;
            if (_valueIsSet)
            {
                _selectList.SetSelected(_value);
            }
        }
    }
}

I find using _valueIsSet clumsy and would much prefer a Nullable<TScalar> where Nullable simply "does nothing" if TScalar is already nullable.

Basically, I want a generic generic type, e.g:

private MagicVoodooType<TScalar> _value;


Where :
1. When TScalar is nullable, e.g. string, then _value will have type TScalar.
2. When TScalar is not nullable, e.g. int, then _value will have type Nullable<TScalar>.

I know this is a long shot, but I have been through discussions of this before, on another board, and some commenters gave me the impression it might be possible with some magic, i.e. IL level stuff, but seeing as the .NET framework has advanced a lot since my first encounter with this requirement, I was wondering if it might be easier now.
Posted
Updated 7-May-15 9:07am
v4
Comments
Philippe Mori 7-May-15 12:18pm    
As far as I know generics in C# don't support that. One workaround might be to store an object instead. And if you need to read selected value from the model, then a cast would be necessary.

If you only want to support value type, then you could add a constraint to the template and then use nullable types.

1 solution

I don't know what you're doing but it looks like you need to determine if TScalar is nullable?

Perhaps you're looking for this:
Type valueType = _value.GetType();

if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
    // Handle the case where TScalar is nullable...
}
else
{
    // Nope, not nullable.
}
 
Share this answer
 
v4
Comments
Brady Kelly 7-May-15 14:57pm    
No, Dave, I don't want to determine if TScalar is nullable or not. I actually want to not care if it is nullable or not, then have an 'inner' _nullableValue field for both nullable and non-nullable types of TScalar. See my update to the question.
Dave Kreskowiak 7-May-15 15:19pm    
Ah. OK, based on your updated post, you can't do that.
You cannot dynamically change the type of TScalar, which is what you're trying to do.

Generics are a sugar coating for code. The compiler generates new classes and methods automatically at compile-time based on all other code in your project that uses the generic type. For example, if you have two instantiations of your class, new DropDownListViewModel<string> and DropDownListViewModel<int>, the compiler will generate two classes for these situations using your class as the template. The TScalar type place holder will be replaced by string in one class and int in the other.

No code is executed at compile-time to make the modification to the type that you're proposing. You can only make a determination of the type you need at run-time. Unfortunately for you, you'd have to generate a Nullable type dynamically at run-time which is going to be horribly complex for something as simple as a ViewModel class.
Brady Kelly 7-May-15 15:28pm    
Thanks. I guess what feel like clumsy workarounds to me are in fact really simple compared to what evil is required under the covers to keep this truly generic. It looks like using 'object' for the value, and using the generic type parameter only for type checking and casting.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900