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

C# 7.2 "in" keyword in interfaces #1052

Open
baehny opened this issue Jan 26, 2018 · 0 comments
Open

C# 7.2 "in" keyword in interfaces #1052

baehny opened this issue Jan 26, 2018 · 0 comments

Comments

@baehny
Copy link

baehny commented Jan 26, 2018

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
@baehny baehny changed the title C# 7.2 in parameter in interfaces C# 7.2 "in" keyword in interfaces Jan 26, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant