Pergunta

Desculpe-me se este é um ingênuo, mas eu não conseguia obter a combinação certa de palavras-chave para filtrar para baixo os vários tipo de restrição e genéricos perguntas lá fora (como há muito).

Eu tenho duas interfaces - chamá-los de deixar IOnline e IOffline .

Eles estão intimamente relacionados em que eles descrevem contratos quase idênticas, mas uma das principais diferenças entre eles é o contexto em que serão utilizados os implementações concretas. Não é exatamente minhas circunstâncias, mas ilustra bem o problema.

Em seguida, tenho alguns métodos lá fora que fazem o trabalho contra os implementadores concretos destas interfaces. Às vezes, esses métodos só querem lidar com um tipo e não o outro.

bastante simples:

public void DoStuff<T>(string foo) where T : IOnline {}

O kicker está a implementar o código para métodos que podem operar em tipo SEJA. Eu pensei que este seria correto, mas na leitura do erro de compilação, a minha expectativa de que a restrição seria interpretado como "permitir que qualquer tipo T a ser usado genericamente aqui se implementar IOnline OU IOffline", que realmente está sendo interpretado como "Permitir que qualquer tipo T a ser usado genericamente aqui se implementar os dois".

public void DoStuff<T>(string foo) where T : IOnline, IOffline {}

Tentando implementar dois métodos separados com o mesmo nome mas diferentes restrições falha como há questões ambigüidade óbvias - estamos não sobrecarregar uma vez que a lista de parâmetros é a mesma (uma vez que o comportamento desejado é idêntica).

I poderia use dois nomes diferentes para dois métodos diferentes, cada um com a restrição apropriada, mas que parece kludgy e faz outras coisas jusante ser um pé no saco ... factível, não, mas ideal.

Eu sinto que deve haver algo que eu sinto falta aqui ... Eu me sinto perfeitamente confortável em terra genérico, mas esta é a primeira vez que eu já tinha para realizar o que eu estou atrás e eu sinto que estou apenas girando minhas rodas atm.

Foi útil?

Solução

O fornecimento de várias restrições como no seu segundo exemplo é realmente aditivo. O href="http://msdn.microsoft.com/en-us/library/d5x73970.aspx" rel="noreferrer"> página tem um pouco sobre isso.

Você pode fazer suas duas interfaces herdar de uma interface de base, e restringir os métodos para o tipo de base?

Outras dicas

Isto não é talvez uma resposta à sua pergunta, mas eu espontaneamente a sensação de que você pode querer refazer suas interfaces. Da sua pergunta:

Eles estão intimamente relacionados na medida em que descrevem contratos quase idênticos, mas uma das principais diferenças entre deles é o contexto em que a será utilizado implementações concretas.

Meu ponto de vista de interfaces é que são contratos . Eles definem como algo deve olhar , não exatamente como deve comportam ; essa é a tarefa da implementação. Agora, eu não tenho nenhuma informação sobre a sua aplicação ou domínio do problema, mas eu provavelmente iria tentar passar algum tempo na identificação de peças idênticas de essas interfaces e movê-los em uma única interface, e manter apenas os differencies como interfaces separadas. Dessa forma, você talvez pudesse navegar após esses tipos de problemas com mais facilidade.

Eu acho que a maneira padrão em .NET para fazer isso é ter uma interface que contém ambas as funções IOnline e IOffline, em seguida, algumas propriedades que dizem que as funções são realmente implementado em uma classe específica. Você vê este padrão em vários lugares em .NET com coisas como um método Seek () que pode ou não ser implementado e uma propriedade CanSeek que você pode testar.

Não é talvez o projeto mais limpo OO, mas funciona.

perde um pouco da verificação em tempo de compilação, mas eu não consigo ver nenhuma maneira de contornar isso ... Você tem que escolher qual você prefere usar, (eu estou supondo que sua preferência seria on-line):

public void DoStuff<T>(string foo)
{
    Type type = typeof(T);
    if(type.GetInterfaces().Contains(typeof(IOnline)))
         doStuffOnline<T>(foo);
    else if(type.GetInterfaces().Contains(typeof(IOffline)))
         doStuffOffline<T>(foo);
    else
         throw new Exception("T must implement either IOnline or IOffline");
}

private void doStuffOnline<T>(string foo){ // can assume T : IOnline }
private void doStuffOffline<T>(string foo){ // can assume T : IOffline }
scroll top