This statement when run from a console application sets 'x' to true
:
var x = 3.GetType().IsAssignableTo(typeof(INumber<>)); // x == true
The same statement when run inside a unit test sets x
to false
. Why?
This statement when run from a console application sets 'x' to true
:
var x = 3.GetType().IsAssignableTo(typeof(INumber<>)); // x == true
The same statement when run inside a unit test sets x
to false
. Why?
This was a bug that was introduced in .NET 6, and fixed in .NET 8.
The correct behaviour is that uninstantiated generics are not AssignableTo.
I guess this makes sense, as you can't write INumber<> x = 3
.
The actual question should be "why it returns true
" and that is targeted by @canton7, but in addition to it I would like to add corresponding quote from the Type.IsAssignableTo
docs:
Returns
true
if any of the following conditions is true:
- The current instance and targetType represent the same type.
- The current type is derived either directly or indirectly from targetType. > - The current type is derived directly from targetType if it inherits from targetType;
- the current type is derived indirectly from targetType if it inherits from a succession of one or more classes that inherit from targetType.
- targetType is an interface that the current type implements.
- The current type is a generic type parameter, and targetType represents one of the constraints of the current type.
- The current type represents a value type, and
targetType
representsNullable<c>
.
false
if none of these conditions are true, or iftargetType
is null.
Since none of true
ones match the case the check should always has returned false
.
Change your code to:
var isINumber = 3.GetType()
.GetInterfaces()
.Any(i => i.IsConstructedGenericType && i.GetGenericTypeDefinition() == typeof(INumber<>))
Or
var isINumberOfInt32 = 3.GetType().IsAssignableTo(typeof(INumber<int>));
I will assume that your question can be translated to "how may the result of false be logically explained", rather than to "what was the exact purpose of the developers of the language/framework".
I am not a developer of the language/framework, so I can only make sense of the logic based on what is publicly available.
https://learn.microsoft.com/en-us/dotnet/api/system.numerics.inumber-1?view=net-8.0
We can see that INumber<TSelf>
is basically a "number of TSelf". And TSelf
can be as follows:
Now, your System.Int32
is a signed value stored on 32 bits. It can overflow a System.Int16
, for example, which is a perfectly valid possibility for TSelf
, so, potentially you have overflows, which, as a possibility makes a false
more correct than a true
for your unit test.