Skip to content
This repository was archived by the owner on Aug 24, 2022. It is now read-only.
This repository was archived by the owner on Aug 24, 2022. It is now read-only.

C# 7.2 "in" keyword in interfaces #1052

@baehny

Description

@baehny

The in C# 7.2 introduced "in" keyword for method parameters results in a crash when used in an interface, but only if the class that is implementing the interface is cast back to the interface.
The code throws a System.InvalidCastException at runtime (Firefox 57.0.4).

Bug test project:
https://github.com/baehny/Bugs/tree/master/JSIL/JSIL_InParameters/JSIL_InParameters

using System;
public struct TestStruct
{
    public int Field;
}
public interface TestInterface
{
    void TestMethodRef(ref TestStruct testStruct);
    void TestMethodIn(in TestStruct testStruct);
}
public class TestClass : TestInterface
{
    public void TestMethodRef(ref TestStruct testStruct) { }
    public void TestMethodIn(in TestStruct testStruct) { }
}
class Program
{
    static void Main(string[] args)
    {
        TestStruct testStruct = new TestStruct();
        TestClass interfaceClass = new TestClass();

        Console.WriteLine("1:");
        interfaceClass.TestMethodRef(ref testStruct); //Works

        Console.WriteLine("2:");
        interfaceClass.TestMethodIn(testStruct); //Works

        Console.WriteLine("3:");
        ((TestInterface)interfaceClass).TestMethodRef(ref testStruct); //Works

        Console.WriteLine("4:");
        ((TestInterface)interfaceClass).TestMethodIn(testStruct); //Crash: throws System.InvalidCastException: Unable to cast object of type 'TestStruct' to type 'ref TestStruct'

        Console.WriteLine("End");
    }
}

There is no problem when using "ref" which is strange because in both cases the parameter is passed as valuetype TestStruct& but with a System.Runtime.InteropServices.InAttribute for the "in" parameter version. However the in keyword results in two definitions for TestMethodIn()

First version of TestMethodIn :

.method public hidebysig 
	instance void TestMethodIn (
		valuetype TestStruct& testStruct
	) cil managed 
{
	.param [1]
	.custom instance void [mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = (
		01 00 00 00
	)
	// Method begins at RVA 0x2050
	// Code size 2 (0x2)
	.maxstack 8

	IL_0000: nop
	IL_0001: ret
} // end of method TestClass::TestMethodIn

Second version of TestMethodIn :

.method private final hidebysig newslot virtual 
	instance void TestInterface.TestMethodIn (
		valuetype TestStruct& modreq([mscorlib]System.Runtime.InteropServices.InAttribute)  testStruct
	) cil managed 
{
	.override method instance void TestInterface::TestMethodIn(valuetype TestStruct& modreq([mscorlib]System.Runtime.InteropServices.InAttribute) )
	.param [1]
	.custom instance void [mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = (
		01 00 00 00
	)
	// Method begins at RVA 0x205c
	// Code size 8 (0x8)
	.maxstack 8

	IL_0000: ldarg.0
	IL_0001: ldarg.1
	IL_0002: call instance void TestClass::TestMethodIn(valuetype TestStruct&)
	IL_0007: ret
} // end of method TestClass::TestInterface.TestMethodIn

TestMethodRef :

.method public final hidebysig newslot virtual 
	instance void TestMethodRef (
		valuetype TestStruct& testStruct
	) cil managed 
{
	// Method begins at RVA 0x2050
	// Code size 2 (0x2)
	.maxstack 8

	IL_0000: nop
	IL_0001: ret
} // end of method TestClass::TestMethodRef

Calling code:

	IL_0037: ldstr "3:"
	IL_003c: call void [mscorlib]System.Console::WriteLine(string)
	IL_0041: nop
	IL_0042: ldloc.1
	IL_0043: ldloca.s 0
	IL_0045: callvirt instance void TestInterface::TestMethodRef(valuetype TestStruct&)
	IL_004a: nop
	IL_004b: ldstr "4:"
	IL_0050: call void [mscorlib]System.Console::WriteLine(string)
	IL_0055: nop
	IL_0056: ldloc.1
	IL_0057: ldloca.s 0
	IL_0059: callvirt instance void TestInterface::TestMethodIn(valuetype TestStruct& modreq([mscorlib]System.Runtime.InteropServices.InAttribute) )
	IL_005e: nop

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions