В Scala я могу определить структурные типы следующим образом:
type Pressable = { def press(): Unit }
Это означает, что я могу определить функцию или метод, который берет в качестве аргумента что-то, что является Pressable, как это:
def foo(i: Pressable) { // etc.
Объект, который я передаю этой функции, должно быть, определил для нее метод, названный нажатием (), который соответствует подписи типа, определенной в типе - не берет аргументов, Единица возвратов (версия Scala пустоты).
Я могу даже использовать структурный встроенный тип:
def foo(i: { def press(): Unit }) { // etc.
Это в основном позволяет программисту обладать всеми преимуществами утиного ввода, все еще обладая преимуществом проверки типа времени компиляции.
C# имеет что-то подобным? Я Погуглил, но ничего не могу найти, но я не знаком с C# ни в какой глубине. Если нет, там какие-либо планы добавить это?
Нет, и никаких планов, о которых я знаю. Только именованные (а не структурные) подтипы (например, интерфейсы).
(Другие могут также захотеть увидеть
http://en.wikipedia.org/wiki/Nominative_type_system
http://en.wikipedia.org/wiki/Structural_type_system
)
( Некоторые люди могут указать на некоторые экзотические угловые случаи, такие как оператор foreach
, использующий структурную типизацию для GetEnumerator
, но это скорее исключение , чем правило).
Как отмечали другие, это на самом деле не доступно в .NET (поскольку это больше вопрос времени выполнения, чем языка). Однако .NET 4.0 поддерживает аналогичные вещи для импортированных COM-интерфейсов, и я считаю, что это можно было бы использовать для реализации структурной типизации для .NET. См. Это сообщение в блоге:
Я сам еще не пробовал играть с этим, но я думаю, что это может позволить авторам компиляторов писать языки со структурной типизацией для .NET. (Идея состоит в том, что вы (или компилятор) определите интерфейс за сценой, но это будет работать, потому что интерфейсы будут рассматриваться как эквивалентные благодаря функции эквивалентности COM).
Кроме того, C # 4.0 поддерживает ключевое слово dynamic
, которое, как мне кажется, можно интерпретировать как структурную типизацию (без проверки статического типа). Ключевое слово позволяет вам вызывать методы для любого объекта, не зная (во время компиляции), будут ли у объекта требуемые методы. По сути, это то же самое, что и проект «Утиная типизация», упомянутый Игорем (но это, конечно, не правильная структурная типизация).
Не существует способа определения структурных типов, имеющих определенную функцию. Существует библиотека, добавляющая поддержку утиной типизации в 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);
}
}