C# имеет эквивалент структурному вводу Scala?

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

type Pressable = { def press(): Unit }

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

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

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

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

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

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

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

18
задан missingfaktor 14 May 2010 в 01:12
поделиться

3 ответа

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

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

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

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

)

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

11
ответ дан 30 November 2019 в 08:37
поделиться

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

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

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

5
ответ дан 30 November 2019 в 08:37
поделиться

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

Это пример из проекта Duck Typing. Обратите внимание, что утиная типизация происходит во время выполнения и может быть неудачной. Насколько я понимаю, эта библиотека также генерирует прокси для типов, которые типизируются 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);
 }
}
7
ответ дан 30 November 2019 в 08:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: