Есть ли в C # эквивалент структурной типизации Scala? - PullRequest
17 голосов
/ 14 мая 2010

В Scala я могу определить структурные типы следующим образом:

type Pressable = { def press(): Unit }

Это означает, что я могу определить функцию или метод, который принимает в качестве аргумента что-то, что является нажимаемым, например:

def foo(i: Pressable) { // etc.

Объект, который я передаю этой функции, должен был определить для него метод с именем press (), который соответствует сигнатуре типа, определенной в типе - не принимает аргументов, возвращает Unit (версия void в Scala).

Я даже могу использовать встроенный структурный тип:

def foo(i: { def press(): Unit }) { // etc.

Это в основном позволяет программисту использовать все преимущества печатания на клавиатуре при одновременной проверке типов во время компиляции.

Есть ли в C # нечто подобное? Я гуглил, но ничего не могу найти, но я не знаком с C # в любой глубине. Если нет, есть ли планы добавить это?

Ответы [ 4 ]

11 голосов
/ 14 мая 2010

Нет, и никаких планов, о которых я знаю. Только именованный (а не структурный) подтип (например, интерфейсы).

(Другие могут захотеть увидеть также

http://en.wikipedia.org/wiki/Nominative_type_system

http://en.wikipedia.org/wiki/Structural_type_system

)

(Некоторые люди могут указать на некоторые экзотические угловые случаи, такие как оператор foreach, использующий структурную типизацию для GetEnumerator, но это скорее , чем правило.)

7 голосов
/ 14 мая 2010

Нет способа определить структурные типы, которые имеют определенную функцию.Существует библиотека, в которую добавлена ​​поддержка Duck Typing для C #, которую можно найти здесь .

Это пример из проекта Duck Typing.Пожалуйста, обратите внимание, что типизирование утки происходит во время выполнения и может дать сбой .Насколько я понимаю, эта библиотека генерирует прокси-серверы для типов, которые являются типизированными по типу утки, что далеко от элегантной поддержки во время компиляции, которой пользуется в Scala.Скорее всего, это так же хорошо, как и с этим поколением C #.

public interface ICanAdd
{
    int Add(int x, int y);
}

// Note that MyAdder does NOT implement ICanAdd, 
// but it does define an Add method like the one in ICanAdd:
public class MyAdder
{
    public int Add(int x, int y)
    {
        return x + y;
    }
}

public class Program
{
    void Main()
    {
        MyAdder myAdder = new MyAdder();

        // Even though ICanAdd is not implemented by MyAdder, 
        // we can duck cast it because it implements all the members:
        ICanAdd adder = DuckTyping.Cast<ICanAdd>(myAdder);

        // Now we can call adder as you would any ICanAdd object.
        // Transparently, this call is being forwarded to myAdder.
        int sum = adder.Add(2, 2);
    }
}

Это способ C # добиться того же, используя хорошие старые интерфейсы.

interface IPressable {
  void Press();
}

class Foo {
 void Bar(IPressable pressable) {
    pressable.Press();
 }
}

class Thingy : IPressable, IPushable, etc {
 public void Press() {
 }
}

static class Program {
 public static void Main() {
  pressable = new Thingy();
  new Foo().Bar(pressable);
 }
}
5 голосов
/ 14 мая 2010

Как уже отмечалось, это не на самом деле , доступное в .NET (так как это больше вопрос времени выполнения, чем языка). Однако .NET 4.0 поддерживает аналогичные функции для импортированных COM-интерфейсов, и я считаю, что это можно использовать для реализации структурной типизации для .NET. Смотрите этот пост в блоге:

Я сам еще не пробовал поиграть с этим, но думаю, что это может позволить авторам компилятора писать языки со структурной типизацией для .NET. (Идея состоит в том, что вы (или компилятор) определите интерфейс за сценой, но он будет работать, потому что интерфейсы будут рассматриваться как эквивалентные благодаря функции эквивалентности COM).

Кроме того, C # 4.0 поддерживает ключевое слово dynamic, которое, я думаю, можно интерпретировать как структурную типизацию (без проверки статического типа). Ключевое слово позволяет вам вызывать методы для любого объекта, не зная (во время компиляции), будут ли у объекта необходимые методы. По сути, это то же самое, что упомянутый Игорем проект «Утиная типизация» (но это, конечно, не правильная структурная типизация).

1 голос
/ 01 января 2016

Ожидаемый шаблон в C # может быть интерпретирован как ограниченный, специальный случай структурного подтипирования / экзистенциальной типизации. Компилятор будет только await объектов, которые имеют доступ к GetAwaiter() методу, который возвращает любой INotifyCompletion объект с определенным набором методов и свойств. Поскольку ни объект «ожидание», ни объект «ожидание» не должны реализовывать какой-либо интерфейс (за исключением INotifyCompletion в случае последнего), await похож на метод, который принимает структурно типизированные ожидаемые объекты.

...