Is casting expensive?

There are actually two different implementations of UClass::IsChildOf (which is used by IsA).

See Engine Source on GitHub

https://github.com/EpicGames/UnrealEngine/blob/d94b38ae3446da52224bedd2568c078f828b4039/Engine/Source/Runtime/CoreUObject/Public/UObject/Class.h#L480
https://github.com/EpicGames/UnrealEngine/blob/99b6e203a15d04fc7bbbf554c421a985c1ccb8f1/Engine/Source/Runtime/CoreUObject/Private/UObject/Class.cpp#L2197

The implementation is chosen like

#if UE_EDITOR || HACK_HEADER_GENERATOR
	// On editor, we use the outerwalk implementation because BP reinstancing and hot reload
	// mess up the struct array
	#define USTRUCT_FAST_ISCHILDOF_IMPL USTRUCT_ISCHILDOF_OUTERWALK
#else
	#define USTRUCT_FAST_ISCHILDOF_IMPL USTRUCT_ISCHILDOF_STRUCTARRAY
#endif

The USTRUCT_ISCHILDOF_STRUCTARRAY implementation caches an array of superstructs and the number of bases in the constructor of UStruct. Then the actual IsChildOfUsingStructArray implementation needs to compare only the number of bases as well as whether `` has the given Parent at the corresponding index in its array of superstructs.

See Engine Source on GitHub

https://github.com/EpicGames/UnrealEngine/blob/99b6e203a15d04fc7bbbf554c421a985c1ccb8f1/Engine/Source/Runtime/CoreUObject/Private/UObject/Class.cpp#L4347
https://github.com/EpicGames/UnrealEngine/blob/d94b38ae3446da52224bedd2568c078f828b4039/Engine/Source/Runtime/CoreUObject/Public/UObject/Class.h#L271