Bug 8934 - Arrays in Mono 3.0.2 do not implement IReadOnlyList<T> (as opposed to Microsoft .NET 4.5)
Summary: Arrays in Mono 3.0.2 do not implement IReadOnlyList<T> (as opposed to Microso...
Status: RESOLVED FIXED
Alias: None
Product: Compilers
Classification: Mono
Component: C# ()
Version: unspecified
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Marek Safar
URL:
Depends on:
Blocks: 13879
  Show dependency tree
 
Reported: 2012-12-14 04:56 UTC by jacob.thamsborg
Modified: 2014-07-24 03:22 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
The code explained above (577 bytes, text/plain)
2012-12-14 04:56 UTC, jacob.thamsborg
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description jacob.thamsborg 2012-12-14 04:56:57 UTC
Created attachment 3096 [details]
The code explained above

The following code compiles and runs just fine with Visual Studio 2012 / Windows 7 / .NET 4.5:

  System.Double[] array = { 1.00, 2.00, 3.00 };
  Console.WriteLine("array[0]: {0:F}, array[1]: {1:F}, array[2]: {2:F} ", array[0], array[1], array[2]);
  System.Collections.Generic.IReadOnlyList<System.Double> list = array;
  Console.WriteLine("list[0]:  {0:F}, list[1]:  {1:F}, list[2]:  {2:F} ", list[0], list[1], list2]);

Here is the (unsurprising) output:

  array[0]: 1,00, array[1]: 2,00, array[2]: 3,00
  list[0]:  1,00, list[1]:  2,00, list[2]:  3,00

However, if I try to execute VS-compiled code with Mono 3.0.2 on Windows it complains:

  array[0]: 1.00, array[1]: 2.00, array[2]: 3.00
  System.Double[] doesn't implement interface System.Collections.Generic.IReadOnlyList<System.Double>

And if I try to compile with Mono I get

  Program.cs(13,76): error CS0029: Cannot implicitly convert type `double[]' 
  to `System.Collections.Generic.IReadOnlyList<double>'

Whether this is a bug in Mono or an unspecified Microsoft behaviour of C# 5.0 / .NET 4.5 I do not know. But it is a real discrepancy between Mono and Windows that has caused me some trouble.

thanks

/thamsborg
Comment 1 Zoltan Varga 2013-01-04 20:37:03 UTC
Fixed in master.
Comment 3 Zoltan Varga 2013-08-08 12:09:58 UTC
The fix is in 6.4.2, do you have a testcase ?
Comment 4 Evan Howarth 2013-08-08 12:55:22 UTC
I gave the wrong version number. Xamarin.iOS 6.4.1.1 is installed instead of
6.4.2. More version information is at the end of this comment.

Here's a dummy line of code that fails to compile:

   IReadOnlyList<int> example = new int[0];

Should my version have the fix? If not, what version of should I be using?


=== Xamarin Studio ===

Version 4.0.11 (build 6)
Installation UUID: b52f9c77-8d39-4e85-8b5d-0f0c538638c7
Runtime:
    Mono 3.2.0 ((no/7c7fcc7)
    GTK 2.24.20
    GTK# (2.12.0.0)
    Package version: 302000000

=== Apple Developer Tools ===

Xcode 4.6.3 (2068)
Build 4H1503

=== Xamarin.Mac ===

Xamarin.Mac: Not Installed

=== Xamarin.Android ===

Version: 4.8.0 (Starter Edition)
Android SDK: /Users/cshi/Library/Developer/Xamarin/android-sdk-mac_x86
    Supported Android versions:
        2.1   (API level 7)
        2.2   (API level 8)
        2.3   (API level 10)
        3.1   (API level 12)
        4.0   (API level 14)
        4.0.3 (API level 15)
Java SDK: /usr
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06-451-11M4406)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01-451, mixed mode)

=== Xamarin.iOS ===

Version: 6.4.1.1 (Business Edition)
Hash: 5a0fe54
Branch: 
Build date: 2013-30-07 08:24:03-0400

=== Build Information ===

Release ID: 400110006
Git revision: b8a862fc80adef69bb383dd305619186da9e1f9b
Build date: 2013-07-31 09:26:05+0000
Xamarin addins: e0bfb020a2d4ed62aadd4d6f40bd83dcbac98ae3

=== Operating System ===

Mac OS X 10.8.3
Comment 5 Zoltan Varga 2013-08-08 14:21:36 UTC
So runtime casting works now, but mcs still fails to compile this.

-> mcs

A testcase:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
using System;
using System.Collections.Generic;

public class Tests
{
	public static void Main (String[] args) {
		IReadOnlyList<int> example = new int[0];
	}
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
csc compiles this fine, while mcs fails with:

error CS0029: Cannot implicitly convert type `int[]' to `System.Collections.Generic.IReadOnlyList<int>'
Comment 6 Marek Safar 2013-08-09 05:56:47 UTC
Fixed in master.

Though runtime verification of this is still failing.
Comment 7 Zoltan Varga 2013-08-09 07:36:18 UTC
What is still failing ?
Comment 8 Richard Cook 2014-07-23 16:57:15 UTC
Commit https://github.com/mono/mono/commit/2f334102 fixes the issue of convertibility of arrays to IReadOnlyCollection<T> and IReadOnlyList<T>. IKVM.Reflection.ArrayType.__GetDeclaredInterfaces currently only reports IList<T>, ICollection<T> and IEnumerable<T> as interfaces for arrays:

public override Type[] __GetDeclaredInterfaces()
{
  return new Type[] {
    this.Module.universe.Import(typeof(IList<>)).MakeGenericType(elementType),
    this.Module.universe.Import(typeof(ICollection<>)).MakeGenericType(elementType),
    this.Module.universe.Import(typeof(IEnumerable<>)).MakeGenericType(elementType)
  };
}

This should probably do something like:

        public override Type[] __GetDeclaredInterfaces()
        {
            if (m_isClr45OrLaterTarget)
            {
                return new Type[] {
                    this.Module.universe.Import(typeof(IList<>)).MakeGenericType(elementType),
                    this.Module.universe.Import(typeof(ICollection<>)).MakeGenericType(elementType),
                    this.Module.universe.Import(typeof(IEnumerable<>)).MakeGenericType(elementType),
                    this.Module.universe.Import(typeof(IReadOnlyCollection<>)).MakeGenericType(elementType),
                    this.Module.universe.Import(typeof(IReadOnlyList<>)).MakeGenericType(elementType)
                };
            }
            else
            {
                return new Type[] {
                    this.Module.universe.Import(typeof(IList<>)).MakeGenericType(elementType),
                    this.Module.universe.Import(typeof(ICollection<>)).MakeGenericType(elementType),
                    this.Module.universe.Import(typeof(IEnumerable<>)).MakeGenericType(elementType)
                };
            }
        }
Comment 9 Richard Cook 2014-07-23 17:27:01 UTC
In fact, the correct interface hierarchy would be something like:

For int[]:
System.Collections.Generic.IList<int>
  System.Collections.Generic.ICollection<int>
    System.Collections.Generic.IEnumerable<int>
      System.Collections.IEnumerable
    System.Collections.IEnumerable
  System.Collections.Generic.IEnumerable<int>
    System.Collections.IEnumerable
  System.Collections.IEnumerable
System.Collections.Generic.IReadOnlyList<int>
  System.Collections.Generic.IReadOnlyCollection<int>
    System.Collections.Generic.IEnumerable<int>
      System.Collections.IEnumerable
    System.Collections.IEnumerable
  System.Collections.Generic.IEnumerable<int>
    System.Collections.IEnumerable
  System.Collections.IEnumerable
Comment 10 Marek Safar 2014-07-24 03:22:33 UTC
I think __GetDeclaredInterfaces is specific IKVM method to return only declared interfaces and excluding default ones is fine in this case