Pergunta

No Scala, posso definir tipos estruturais do seguinte modo:

type Pressable = { def press(): Unit }

Isso significa que posso definir uma função ou método que receba como argumento algo que seja pressionável, assim:

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

O objeto que passo para esta função deve ter definido para ele um método chamado press() que corresponda à assinatura de tipo definida no tipo - não aceita argumentos, retorna Unit (versão de void do Scala).

Posso até usar o tipo estrutural inline:

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

Basicamente, ele permite que o programador tenha todos os benefícios da digitação com pato e, ao mesmo tempo, tenha o benefício da verificação de tipo em tempo de compilação.

C# tem algo semelhante?Pesquisei no Google, mas não consigo encontrar nada, mas não estou familiarizado com C# em profundidade.Se não houver, há planos para adicionar isso?

Foi útil?

Solução

Não, e nenhum plano que eu conheço. Apenas nomeado (em vez de estrutural) subtyping (por exemplo, interfaces).

(Outros podem querer ver também

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

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

)

(Algumas pessoas podem apontar alguns casos de canto exóticos, como o foreach declaração usando digitação estrutural para GetEnumerator, mas este é o exceção ao invés da regra.)

Outras dicas

Não há uma maneira de definir tipos estruturais que tenha uma função específica. Há uma biblioteca que adiciona suporte de digitação de pato a C# que pode ser encontrado aqui.

Este é o exemplo do projeto de digitação de patos. Observe o A digitação de pato acontece em tempo de execução e pode falhar. Entendo também que essa biblioteca gera proxies para os tipos digitados por patos, que estão muito longe do elegante suporte de tempo de compilação que é desfrutado em Scala. Isso é mais provável que seja bom com esta geração de 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);
    }
}

Esta é a maneira C# de alcançar a mesma coisa usando as boas interfaces chatas.

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);
 }
}

Como outros observaram, isso não é verdade Disponível no .NET (pois isso é mais uma questão de tempo de execução do que um idioma). No entanto, o .NET 4.0 suporta coisa semelhante para interfaces de comidas importadas e acredito que isso possa ser usado para implementar a digitação estrutural para .NET. Veja esta postagem do blog:

Ainda não tentei brincar com isso, mas acho que poderia permitir que os autores do compilador escrevessem idiomas com digitação estrutural para .NET. (A idéia é que você (ou um compilador) definisse uma interface nos bastidores, mas funcionaria, porque as interfaces seriam tratadas como equivalentes, graças ao recurso de equivalência com).

Além disso, C# 4.0 suporta o dynamic Palavra -chave que, eu acho, poderia ser interpretada como uma digitação estrutural (sem verificação de tipo estático). A palavra-chave permite chamar métodos em qualquer objeto sem conhecer (em tempo de compilação) se o objeto terá os métodos necessários. Isso é essencialmente a mesma coisa que o projeto "Dato digitando" mencionado pelo Igor (mas isso, é claro, não é uma digitação estrutural adequada).

O padrão aguardável em C# talvez possa ser interpretado como uma instância limitada e ad hoc de subtipagem estrutural/tipagem existencial.O compilador só irá await objetos que têm acesso a um GetAwaiter() método que retorna qualquer INotifyCompletion objeto com um conjunto específico de métodos e propriedades.Como nem o objeto 'awaitable' nem o objeto 'awaiter' precisam implementar qualquer interface (exceto INotifyCompletion no caso deste último), await é semelhante a um método que aceita objetos aguardáveis ​​​​de tipo estrutural.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top