简体   繁体   中英

How to tell the difference between typeof(int) == typeof(int?) in C#

Why does C# set these equal?

typeof(int).GetType() == typeof(int?).GetType()

The problem occurs when writing expression trees where I cast the

List<int?> ids = JsonConvert.DeserializeObject<List<int?>>(filter.Value?.ToString());
var filterField = filter.PropertyName;
var method = ids.GetType().GetMethod("Contains");
return Expression.Call(Expression.Constant(ids), method, member);

generates this error

System.ArgumentException: Expression of type 'System.Int32' cannot be used for parameter of type 'System.Nullable 1[System.Int32]' of method 'Boolean Contains(System.Nullable 1[System.Int32])

Is there a way to check the type before sending to the expression tree?

I tried checking the types of int and int? and both return true for the following check:

bool isIntNull = type == typeof(int?).GetType();

Why does C# set these equal?

Because they ARE equal.

typeof(int) generates a RuntimeType instance by the compiler

typeof(int?) generates a different RuntimeType instance by the compiler

calling GetType() on any RuntimeType instance returns the type System.RuntimeType

I think you want

typeof(int) == typeof(int?)

and

bool isIntNull = type.Equals(typeof(int?));

Proof:

Console.WriteLine(typeof(int));
Console.WriteLine(typeof(int?));
Console.WriteLine(typeof(int).GetType());
Console.WriteLine(typeof(int?).GetType());

output:

System.Int32
System.Nullable`1[System.Int32]
System.RuntimeType
System.RuntimeType

The typeof(X) operator always returns a Type object representing the type X . The GetType() method returns the runtime type of the object it is called on. So if you have the expression typeof(X).GetType() the first part of the expression will always return a Type instance, and the second part of that expression will always return a Type object representing the type Type , no matter what X is. You want to compare typeof(int) to typeof(int?) , which are different.

I think, whats wrong with your expression tree is that the member variable is an Expression of type int instead of int? . The code you posted didn't show where it is coming from, but I think the following would help you:

return Expression.Call(Expression.Constant(ids), method, Expression.Convert(member, typeof(int?)));

搜索答案并尝试此处的所有内容后,发现了这一点。

bool isIntNull = member.Type.IsGenericType && member.Type.GetGenericTypeDefinition() == typeof(Nullable<>);

I have the same problem extracting data of an unknown runtime datatype to a known datatype - I solved the problem this way.

public bool CompareDataType<T>(Type runtimedatatype)
{
    Type KT = typeof(T);

    return runtimedatatype.Equals(KT) || runtimedatatype.Equals(Nullable.GetUnderlyingType(KT));
}

int? output = null;
object RunTimeData = (object)((int)0);
if (CompareDataType<int?>(RunTimeData.GetType()))
    output = (int?)RunTimeData;

Alternatively you can create an extension of Object (which is what I went with in the end)

public static class ObjectTypeIsEqual
{
    public static bool CompareDataType<T>(this object input)
    {
        Type ObjectType = input.GetType();
        Type CompareType = typeof(T);

        return ObjectType.Equals(CompareType) || ObjectType.Equals(Nullable.GetUnderlyingType(CompareType));
    }
}

int? output = null;
object RunTimeData = (object)((int)0);
if (RunTimeData.CompareDataType<int?>())
    output = (int?)RunTimeData;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM