1

I have the following code:

Tuple<string, string, Type, ParameterInfo[]> method = (Tuple<string, string, Type, ParameterInfo[]>)(comboBox1.SelectedItem);
if (comboBox2.SelectedIndex - 1 >= 0)
{
    if (method.Item4[comboBox2.SelectedIndex - 1].ParameterType.BaseType == typeof(Enum))
    {
        foreach (object type in Enum.GetValues(method.Item4[comboBox2.SelectedIndex - 1].ParameterType))
        {
            Console.WriteLine(type);
        }
        MessageBox.Show("This looks like an auto-generated type; you shouldn't set it to anything.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
    }
    else if (Nullable.GetUnderlyingType(method.Item4[comboBox2.SelectedIndex - 1].ParameterType) != null)
    {
        if (Nullable.GetUnderlyingType(method.Item4[comboBox2.SelectedIndex - 1].ParameterType).BaseType == typeof(Enum))
        {
            MessageBox.Show("This looks like an auto-generated type; you shouldn't set it to anything.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
        }
    }
}

On the else if statement, I noticed that it always returns null, even though the object at method.Item4[0] in my case is always a Nullable type when the comboBox2.SelectedIndex is 1, so why is it returning null? Seriously, I put a break-point there, and in Item4, I see the object at index 0 as:

[0] = {System.Nullable`1[CarConditionEnum]& carCondition}

...and at index 1 as:

[1] = {Boolean& carConditionSpecified}

Marc
  • 3,905
  • 4
  • 21
  • 37
Alexandru
  • 12,264
  • 17
  • 113
  • 208
  • Possible duplicate http://stackoverflow.com/questions/374651/how-to-check-if-an-object-is-nullable – Dustin Kingen Feb 06 '13 at 20:19
  • 1
    It's hard to reproduce from the code you give here. Clearly the `ParameterInfo` which is shown as ``{System.Nullable`1[CarConditionEnum]& carCondition}`` should have a `ParameterType` that is `CarConditionEnum?`, so nullable. Are you sure the index to the array is correct? – Jeppe Stig Nielsen Feb 06 '13 at 20:30
  • @JeppeStigNielsen - Well, if under the first if statement I include these two lines: string s1 = method.Item4[comboBox2.SelectedIndex - 1].ParameterType.ToString(); string s2 = method.Item4[comboBox2.SelectedIndex - 1].ToString(); ...a breakpoint will show me that s1 is: s1 = "System.Nullable`1[CarConditionEnum]&" ...and s2 is: s2 = "System.Nullable`1[CarConditionEnum]& carCondition" – Alexandru Feb 06 '13 at 20:33
  • 1
    Another tip: Instead of saying `.BaseType == typeof(Enum)` (two places), you can simply use `.IsEnum`. – Jeppe Stig Nielsen Feb 06 '13 at 21:27

2 Answers2

4

The problem is the parameter is a by reference type i.e. it is declared as ref CarConditionEnum? paramName.

You need to get the element type of the parameter, and then use Nullable.GetUnderlyingType:

Type paramType = method.Item4[comboBox2.SelectedIndex - 1].ParameterType;
if(paramType.HasElementType)
{
    paramType = paramType.GetElementType();
}

if(Nullable.GetUnderlyingType(paramType) != null)
{
}
Lee
  • 142,018
  • 20
  • 234
  • 287
  • Ah, couldn't find out how to remove that ByRef "wrapping" of the type. I didn't think of `GetElementType()`. It looks like `GetElementType` can be used to undo either `MakeArrayType()`, `MakePointerType()`, or `MakeByRefType()`. That's nice to know. – Jeppe Stig Nielsen Feb 06 '13 at 21:09
1

The problem is that the parameter is ref or out which I can see from the ampersand & character. At first I didn't know how to remove that, but it turned out (the other answer) that you use GetElementType() for that.

I reproduce your findings like this:

var t1 = typeof(int?);
string s1 = t1.ToString();  // "System.Nullable`1[System.Int32]"
bool b1 = Nullable.GetUnderlyingType(t1) != null;  // true

var t2 = t1.MakeByRefType();
string s2 = t2.ToString();  // "System.Nullable`1[System.Int32]&"
bool b2 = Nullable.GetUnderlyingType(t2) != null;  // false

// remove the ByRef wrapping
var t3 = t2.GetElementType();
string s3 = t3.ToString();  // "System.Nullable`1[System.Int32]" 
bool b3 = Nullable.GetUnderlyingType(t3) != null;  // true

Here, t1 and t3 are the same type, ReferenceEquals(t1, t3).

Community
  • 1
  • 1
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • 1
    @Servy First version of my answer did contain the correct explanation of why the code of the original question didn't work. But I admit it wasn't very clear. Hopefully it's better now, and now I learned from Lee's answer how to get rid of the ByRef stuff that was sticking with the type. – Jeppe Stig Nielsen Feb 06 '13 at 21:16