Порядок реализации контравариантного интерфейса - PullRequest
3 голосов
/ 22 октября 2019

Взять этот кусок кода:

using System;

public class Program
{
    interface IVisitable<T> { 
        void Accept(object o);
    }

    interface IVisitor<in T> {
        void Visit(T t);
    }

    class IntAndDoubleVisitable: IVisitable<int>, IVisitable<double>
    {
        public void Accept(object o) {
            if (o is IVisitor<IntAndDoubleVisitable>) {
                ((IVisitor<IntAndDoubleVisitable>)o).Visit(this);
            }
        }
    }

    class SingleVisitor<T>: IVisitor<T> {
        public void Visit(T visitor) {
            Console.WriteLine(typeof(T).FullName);
        }
    }

    class DoubleVisitor1: IVisitor<IVisitable<int>>, IVisitor<IVisitable<double>> {
        void IVisitor<IVisitable<int>>.Visit(IVisitable<int> t) {
            Console.WriteLine("Int");
        }

        void IVisitor<IVisitable<double>>.Visit(IVisitable<double> t) {
            Console.WriteLine("Double");
        }
    }

    class DoubleVisitor2: IVisitor<IVisitable<double>>, IVisitor<IVisitable<int>> {
        void IVisitor<IVisitable<int>>.Visit(IVisitable<int> t) {
            Console.WriteLine("Int");
        }

        void IVisitor<IVisitable<double>>.Visit(IVisitable<double> t) {
            Console.WriteLine("Double");
        }
    }

    public static void Main()
    {
        var visitable = new IntAndDoubleVisitable();
        visitable.Accept(new SingleVisitor<IVisitable<int>>()); // Fine
        visitable.Accept(new SingleVisitor<IVisitable<double>>()); // Fine
        visitable.Accept(new DoubleVisitor1()); // ?
        visitable.Accept(new DoubleVisitor2()); // ?
    }
}

Как будут обрабатываться как минимум два вызова?

Проведя несколько тестов, я могу сказать, что первый вызов (DoubleVisitor1) пишет "Int ", а второй пишет" Double ", но я не смог найти в Интернете ничего, кроме поста Эрика Липперта, дразнящего о том, что вызовет та же ситуация, если его использовать в IEnumerable. Было бы неплохо иметь ссылку на язык или документацию Microsoft.

1 Ответ

6 голосов
/ 22 октября 2019

На уровне IL поведение определяется в ECMA 335 (II.12.2) в порядке декларации со ссылкой на таблицы декларации IL . Однако AFAIK C # формально не гарантирует сохранение порядка объявления интерфейса из C # в IL , поэтому:

  • случается с быть порядком объявления сегодня
  • но было бы разумно считать это неопределенным поведением, а не полагаться на него
  • и, в частности, заметить, что C # может иметь неопределенный порядок объявления в любом случае (см .: partial class)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...