Herdar de uma classe base genérica, aplicar uma restrição e implementar uma interface em C #

117

Esta é uma questão de sintaxe. Eu tenho uma classe genérica que está herdando de uma classe base genérica e está aplicando uma restrição a um dos parâmetros de tipo. Também quero que a classe derivada implemente uma interface. Pela minha vida, não consigo descobrir a sintaxe correta.

Isso é o que eu tenho:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar { ... }

A primeira coisa que me veio à mente foi:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar, IFoo { ... }

Mas isso é incorreto, pois faz com que T2 precise implementar IBar e IFoo, não DerivedFoo para implementar IFoo.

Tentei pesquisar um pouco no Google, usar dois-pontos, ponto e vírgula, etc., mas não consegui. Tenho certeza de que a resposta é extremamente simples.

Dan Rigby
fonte
Não pude entender a resposta de @Adam quando olhei uma vez, mas depois de 2 minutos consegui entender o que é, obrigado pela resposta. A classe derivada tem mais de uma implementação, talvez este seja o ponto. De qualquer forma, quero mostrar sua notação para os outros. "class DerivedClass <Type>: ParentClass onde Type: IType". Nada deve estar entre a última classe implementada e a cláusula where.
nurisezgin de

Respostas:

173

Você inclui a assinatura inteira de sua classe antes de definir restrições genéricas.

class DerivedFoo<T1, T2> : ParentFoo<T1, T2>, IFoo where T2 : IBar
{
    ...
}
Adam Robinson
fonte
5
Para outros, internalizei isso como, uma classe só obtém uma cláusula where, e vai no final para qualquer e todas as restrições de tipo genérico.
Andy V
@Visser É permitido ter cláusulas where múltiplas, classe Test <T1, T2> onde T1: Interface1 onde T2: Interface2
bwing
@Visser sim, o que o bwing disse, também cada cláusula where pode ter várias restrições ... então a sintaxe do post original está correta, significa apenas algo diferente que o op queria. where T2 : IBar, IFoo apenas significa que T2deve implementar ambas as interfaces em vez de DerivedFoo<T1,T2> implementarIFoo
v01pe
18

Minha recomendação: quando você tiver uma dúvida sobre a sintaxe da linguagem C #, leia a especificação; é por isso que o publicamos. Você vai querer ler a seção 10.1.

Para responder à sua pergunta específica, a ordem das coisas em uma declaração de classe é:

  • atributos, entre colchetes
  • modificadores ("público", "estático" e assim por diante)
  • "parcial"
  • "classe"
  • o nome da classe
  • uma lista separada por vírgulas de declarações de parâmetro de tipo dentro de colchetes angulares
  • dois pontos seguidos de uma lista separada por vírgulas de tipos base (classe base e interfaces implementadas, classe base deve ir primeiro se houver)
  • restrições de parâmetro de tipo
  • o corpo da classe, cercado por colchetes
  • um ponto e vírgula

Tudo nessa lista é opcional, exceto "classe", o nome e o corpo, mas tudo deve aparecer nessa ordem se aparecer.

Eric Lippert
fonte
95
Eric, embora eu o respeite muito como profissional e aprecie seus comentários, não posso deixar de ficar frustrado com o que parece ser uma resposta abrasiva. Você está me criticando por escolher fazer uma pergunta em um site de perguntas e respostas de programação em vez de localizar, baixar e pesquisar em um documento Word de 503 páginas altamente técnico enterrado em um link no MSDN. Isso é muito difícil. Este foi o uso mais eficiente do meu tempo e tem a vantagem adicional de poder ajudar alguém mais tarde. O link para as especificações C # Lang para os interessados ​​é: msdn.microsoft.com/en-us/vcsharp/aa336809.aspx
Dan Rigby
17
Nenhuma crítica foi intencional. Existe um preconceito generalizado na comunicação de texto puro que faz com que declarações simples de fatos pareçam bruscas e abrasivas; Tento ler com caridade quando apresentado a uma lista de fatos úteis e recomendo que você faça o mesmo. Eu mantenho minha recomendação; se você tiver dúvidas sobre sintaxe, a especificação as responde definitivamente e começa com um índice útil para localizar definições de sintaxes específicas.
Eric Lippert
3
Dan, encontrar a especificação C # é tão simples quanto inserir 'C # Spec' no Google e clicar no botão 'Tô com sorte'. E se você é um desenvolvedor C # profissional, você já deve ter especificações C # em formato PDF em sua máquina. Além disso, também não quero criticar você. Eu não estava acostumado a ler especificações antes, mas comecei a ler graças a Jon, Eric e Pavel que sempre citam a especificação C # para qualquer pergunta. Descobri que a especificação C #, embora às vezes seja difícil de ler, é uma ótima maneira de aprender sobre a linguagem.
SolutionYogi
@Eric Lippert: Muito justo. Obrigado por sua resposta. Como uma sugestão construtiva, seria útil se a Microsoft integrasse o conteúdo da especificação diretamente no MSDN, além de tê-lo como um download separado. A versão do Visual Studio .Net MSDN tem uma versão integrada da especificação, mas não versões posteriores. Pensei em comprar o livro de Anders Hejlberg, mas com o .Net 4.0 chegando, estou relutante em comprar. amazon.com/C-Programming-Language-3rd/dp/0321562992 Obrigado.
Dan Rigby
2
C ++ requer que uma declaração de classe termine em um ponto-e-vírgula. Muitos desenvolvedores C # vêm de uma formação em C ++; às vezes seus dedos colocam o ponto-e-vírgula sem que o cérebro se envolva. :-) Há uma série de construções em C # que levam um semi opcional onde C ++ requer um. É basicamente uma conveniência sutil. Suponho que também permite que você chame sutilmente quando uma declaração de tipo está terminando em vez de dizer uma declaração de corpo de método.
Eric Lippert
8
public interface IFoo {}
public interface IBar {}

public class ParentFoo<T,T1> { }
public class DerivedFoo<T, T1> : ParentFoo<T, T1>, IFoo where T1 : IBar { }
Stan R.
fonte
2
public class KeyAndValue<T>
{
    public string Key { get; set; }
    public virtual T Value { get; set; }
}

public class KeyAndValue : KeyAndValue<string>
{
    public override string Value { get; set; }
}

Esta é uma extensão das respostas existentes. O padrão é stringse você não fornecer um tipo. Não implementei uma interface, mas isso não deve exigir nada diferente do normal.

user875234
fonte