Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# operator 'is' arguments

I am developing a small game for the fun of it and I stumbled upon a confusing moment with C#'s is operator. Here is the code:

public static InventorySlot FindSlotWithItem(this IInventory inventory, Type itemType)
{
    return inventory.InventorySlots.FirstOrDefault(t => t is itemType);
}

As it stands, this code doesn't compile as my Visual Studio tells me that type or namespace name 'itemType' could not be found. I was wondering why that is and looked for a bit of information on MSDN. And here is what I found:

is (C# Reference): Checks if an object is compatible with a given type. For example, the following code can determine if an object is an instance of the MyObject type, or a type that derives from MyObject

And these lines got me even more confused as I am clearly passing an object as the first parameter and the type as the second. I understand that this is connected to the fact that compiler looks for a type called 'itemType', but this is not exactly the behavior I want.

Please tell me why such syntax is not working and why 'itemType' is not considered a type by 'is' operator.

like image 305
MarengoHue Avatar asked Dec 12 '22 01:12

MarengoHue


2 Answers

The issue here is that the objects of the Type class are not the same as the compile-time constant reference to a class. Instead, Type objects are just objects encapsulating the matadata of a class, and they thus can't be used to directly create variables, call static members, pass as generics, or be called with is the way an actual class reference can.

That being said, all the above operations have workarounds utilizing only the metadata. For type comparison, try

t => itemType.IsAssignableFrom(t.GetType());

This will check whether "a variable of type itemType can be assigned a value of type t.GetType()" - which will check not only for typing, but will also nicely accept polymorphic types without complaint.

like image 70
David Avatar answered Dec 18 '22 08:12

David


You can do either this:

public static InventorySlot FindItem<T>(this IInventory inventory)
{
    return inventory.InventorySlots.FirstOrDefault(t => t is T);
}

or this:

public static InventorySlot FindItem(this IInventory inventory, Type itemType)
{
    return inventory.InventorySlots.FirstOrDefault(t => itemType.IsAssignableFrom(t.GetType()));
}
like image 41
Amir Popovich Avatar answered Dec 18 '22 10:12

Amir Popovich