Casting generic interface types

RemObjects Elements 8.0.80.1623

The issue is that Test3 fails, even though IIntegerType descends from IPrimitiveType.
This appears to be, but hoping it is not a limitation with the .Net framework.
Is there a work around for this, as this breaks a lot of my code that is attempting to be cross platform with Delphi?
You guessed it, Delphi allows casting this way.

namespace CastTypes;

interface

type
  IAnyType = interface;
  AnyType = class(Object, IAnyType);

  IPrimitiveType = interface(IAnyType);
  PrimitiveType = class(AnyType, IPrimitiveType);
  
  IPrimitiveTypeList<IPrimitiveType> = interface(IAnyType);  
  PrimitiveTypeList<IPrimitiveType> = class(AnyType, IPrimitiveTypeList<IPrimitiveType>);

  IIntegerType = interface(IPrimitiveType);
  IntegerType = class(PrimitiveType, IIntegerType);

  IIntegerList = interface(IPrimitiveTypeList<IIntegerType>);
  IntegerList = class(PrimitiveTypeList<IntegerType>, IIntegerList);

  ConsoleApp = class
  public
    class method Main (args: array of String);
    class method Test1 (value: IAnyType);
    class method Test2 (value: IAnyType);
    class method Test3 (value: IAnyType);
  end;

implementation

class method ConsoleApp.Main (args: array of String);
begin
  var value: IAnyType := new IntegerList; 

  Test1 (value);
  Test2 (value);
  // This test fails
  Test3 (value);

  Console.ReadKey;
end;

class method ConsoleApp.Test1 (value: IAnyType);
begin
  if value is IIntegerList then begin
    Console.WriteLine ('value is IIntegerType list');
  end;
end;

class method ConsoleApp.Test2 (value: IAnyType);
begin
  if value is IPrimitiveTypeList<IIntegerType> then begin
    Console.WriteLine ('value is IIntegerType list');
  end;
end;

class method ConsoleApp.Test3 (value: IAnyType);
begin
  if value is IPrimitiveTypeList<IPrimitiveType> then begin
    Console.WriteLine ('value is IPrimitiveType list');
  end else begin
    Console.WriteLine ('FAIL');
  end;
end;

end.

So the issue here is that

 IPrimitiveTypeList<IPrimitiveType>

and

 IPrimitiveTypeList<IntegerType>

are two completely different different types, as far as .NET sees it, in .NET you can even implement both on your class and have different behavior. Now Delphi uses guids for interfaces and when doing IS it compares that, problem there is that Delphi event lets you do IPrimitiveTypeList<String> and it will return true for the is.

Now .NET since 4.0 DOES support co/contra variance in interfaces, where you can define:

    IPrimitiveTypeList<out IPrimitiveType> = interface(IAnyType);

and it gives you the result you want, note however there are restrictions on the places you can then use IPrimitiveType in the interface definition. See http://www.elementswiki.com/en/Generic_Variance for more details and restrictions.

Thanks for the directions.
I reckon I have some studying to do.