Compartilhar via


Resolver erros e avisos relacionados a parâmetros de tipo genérico e argumentos de tipo genérico

Este artigo aborda os seguintes avisos do compilador:

  • CS0080: restrições não são permitidas em declarações não genéricas.
  • CS0081: a declaração de parâmetro de tipo deve ser um identificador, não um tipo.
  • CS0224: um método com vararg não pode ser genérico, estar em um tipo genérico ou ter um parâmetro params.
  • CS0304: Não é possível criar uma instância do tipo de variável porque ela não tem a new() restrição.
  • CS0305: o uso do tipo genérico requer argumentos de tipo N.
  • CS0306: O tipo pode não ser usado como um argumento de tipo.
  • CS0307: O identificador não é um método genérico. Se você pretendia uma lista de expressões, use parênteses ao redor da expressão.
  • CS0308: O tipo ou método não genérico não pode ser usado com argumentos de tipo.
  • CS0310: O tipo deve ser um tipo não abstrato com um construtor público sem parâmetros para usá-lo como parâmetro no tipo ou método genérico.
  • CS0311: O tipo não pode ser usado como parâmetro T de tipo no tipo genérico ou método. Não há nenhuma conversão de referência implícita do tipo1 para o tipo2.
  • CS0312: O tipo 'type1' não pode ser usado como parâmetro de tipo no tipo genérico ou método. O tipo 'type1' anulável não atende à restrição.
  • CS0313: O tipo 'type1' não pode ser usado como parâmetro de tipo no tipo genérico ou método. O tipo 'type1' anulável não atende à restrição. Tipos que permitem valor nulo não podem atender a nenhuma restrição de interface.
  • CS0314: O tipo não pode ser usado como parâmetro de tipo no tipo genérico ou método. Não há conversão boxing ou conversão de parâmetro de tipo.
  • CS0315: O tipo não pode ser usado como parâmetro T de tipo no tipo genérico ou método. Não há conversão de boxe.
  • CS0401: a new() restrição deve ser a última restrição especificada.
  • CS0403: não é possível converter nulo em parâmetro de tipo porque ele pode ser um tipo de valor não anulável. Considere usar default(T) em vez disso.
  • CS0405: restrição duplicada para o parâmetro de tipo.
  • CS0412: Parâmetro: um parâmetro, uma variável local ou uma função local não pode ter o mesmo nome que um parâmetro de tipo de método.
  • CS0413: O parâmetro de tipo não pode ser usado com o as operador porque ele não tem uma restrição de tipo de classe nem uma restrição class .
  • CS0417: Identificador: não é possível fornecer argumentos ao criar uma instância de um tipo de variável.
  • CS0449: As restrições class, struct, unmanaged, notnull e default não podem ser combinadas ou duplicadas, e devem ser especificadas primeiro na lista de restrições.
  • CS0450: Parâmetro de tipo: não é possível especificar simultaneamente uma classe de restrição e a restrição ou .
  • CS0451: A new() restrição não pode ser usada com a restrição struct .
  • CS0454: dependência de restrição circular envolvendo o Parâmetro de Tipo 1 e o Parâmetro de Tipo 2.
  • CS0455: o parâmetro type herda restrições conflitantes.
  • CS0694: o parâmetro Type tem o mesmo nome que o tipo ou método que contém.
  • CS0695: T não é possível implementar ambas as interfaces porque elas podem unificar algumas substituições de parâmetro de tipo.
  • CS0698: um tipo genérico não pode derivar do tipo porque é uma classe de atributo.
  • CS0702: a restrição não pode ser uma classe especial.
  • CS0703: acessibilidade inconsistente: o tipo de restrição é menos acessível que a declaração.
  • CS0706: tipo de restrição inválido. Um tipo usado como uma restrição deve ser uma interface, uma classe não lacrada ou um parâmetro de tipo.
  • CS0717: classe estática: classes estáticas não podem ser usadas como restrições.
  • CS1961: Variação inválida: o parâmetro de tipo deve ser validamente variante no tipo.
  • CS7002: uso inesperado de um nome genérico.
  • CS8322: não é possível passar argumento com tipo dinâmico para função local genérica com argumentos de tipo inferidos.
  • CS9011: A palavra-chave delegate não pode ser usada como uma restrição. Você quis dizer System.Delegate?
  • CS9012: Palavra-chave recordinesperada. Você quis dizer record struct ou record class?
  • CS9338: Acessibilidade inconsistente: o tipo é menos acessível que a classe.

Declaração e nomenclatura de parâmetro de tipo

Os seguintes erros estão relacionados à forma como você declara e nomeia parâmetros de tipo em tipos e métodos genéricos:

  • CS0080: restrições não são permitidas em declarações não genéricas.
  • CS0081: a declaração de parâmetro de tipo deve ser um identificador, não um tipo.
  • CS0412: Parâmetro: um parâmetro, uma variável local ou uma função local não pode ter o mesmo nome que um parâmetro de tipo de método.
  • CS0694: o parâmetro Type tem o mesmo nome que o tipo ou método que contém.
  • CS9012: Palavra-chave recordinesperada. Você quis dizer record struct ou record class?

Para corrigir esses erros, certifique-se de declarar parâmetros de tipo com identificadores válidos, aplique cláusulas de restrição apenas a declarações genéricas e evite conflitos de nomenclatura com outros identificadores no escopo:

  • Remova a cláusula de restrição de declarações não genéricas (CS0080). A where cláusula só pode ser usada em tipos genéricos e métodos que declaram parâmetros de tipo, pois as restrições definem requisitos que os argumentos de tipo devem satisfazer. Se você precisar aplicar restrições, primeiro adicione parâmetros de tipo à declaração de tipo ou método. Por exemplo, altere public class MyClass where MyClass : System.IDisposable para public class MyClass<T> where T : System.IDisposable.
  • Substitua nomes de tipo reais por identificadores em declarações de parâmetro de tipo (CS0081). Você deve declarar parâmetros de tipo usando identificadores (como T, TKeyou TValue) em vez de tipos concretos (como int ou string). A finalidade de um parâmetro de tipo é servir como um espaço reservado que o compilador substitui por tipos reais quando o tipo ou método genérico é usado. Por exemplo, altere public void F<int>() para public void F<T>().
  • Renomeie parâmetros de tipo, variáveis locais ou parâmetros para evitar conflitos de nomenclatura (CS0412, CS0694). Nomes de parâmetro de tipo não podem sombrear identificadores no mesmo escopo. Eles não podem corresponder ao nome do tipo ou método que contém. Esses conflitos criam ambiguidade sobre qual identificador está sendo referenciado. Por exemplo, se você tiver um método public void F<T>(), não poderá declarar uma variável double T local dentro desse método e não poderá nomear um parâmetro de tipo da mesma forma que seu tipo de contenção (class C<C>).
  • Use a sintaxe da declaração de registro correta (CS9012). Ao declarar um tipo de registro, você deve usar ou record classrecord struct (ou apenas record para um tipo de referência). A record palavra-chave por si só não pode aparecer em posições em que o compilador espera uma sintaxe de declaração de tipo. Por exemplo, se você pretende declarar um tipo de registro, gravar record class MyRecord ou record struct MyRecord em vez de colocar record onde uma palavra-chave diferente é esperada.

Para obter mais informações, consulte Parâmetros de tipo genérico e genéricos.

Declaração de restrição e ordenação

Os seguintes erros estão relacionados à sintaxe e à ordenação de restrições em parâmetros de tipo genérico:

  • CS0401: a new() restrição deve ser a última restrição especificada.
  • CS0449: As classrestrições , , structunmanagednotnulle default , não podem ser combinadas ou duplicadas, e devem ser especificadas primeiro na lista de restrições.
  • CS0450: Parâmetro de tipo: não é possível especificar simultaneamente uma classe de restrição e as restrições class ou struct.
  • CS0451: A new() restrição não pode ser usada com a restrição struct .
  • CS9011: A palavra-chave delegate não pode ser usada como uma restrição. Você quis dizer System.Delegate?

As restrições nos parâmetros de tipo devem seguir uma ordem específica: restrições primárias (class, , struct, unmanagedou notnulldefault) vêm primeiro, seguidas por restrições de interface ou classe e, por fim, a restrição do new() construtor. Algumas restrições são mutuamente exclusivas e não podem ser combinadas.

Para corrigir estes erros:

  • Coloque a new() restrição no final da lista de restrições (CS0401). A new() restrição deve aparecer após todas as outras restrições. Por exemplo, altere where T : new(), IDisposable para where T : IDisposable, new().
  • Coloque as restrições primárias primeiro e não combine restrições mutuamente exclusivas (CS0449). Você pode especificar no máximo um de class, struct, unmanaged, notnullou default, e ele deve aparecer primeiro na lista de restrições. As restrições class e struct são mutuamente exclusivas, assim como class e unmanaged. Em um contexto anulável, class já implica notnull, portanto, eles não podem ser combinados.
  • Não combine uma restrição de classe específica com struct (CS0450). Se um parâmetro de tipo for restrito a um tipo de classe específico, ele será implicitamente um tipo de referência, o que contradiz a struct restrição. Remova a restrição de classe ou a struct restrição.
  • Não combine new() com struct (CS0451). Todos os tipos de valor (structs) têm implicitamente um construtor público sem parâmetros, portanto, a new() restrição é redundante quando combinada com struct. Remova a new() restrição ao usar struct.
  • Substitua delegate por System.Delegate cláusulas de restrição (CS9011). A delegate palavra-chave é usada para declarar tipos delegados, não como uma restrição. Para restringir um parâmetro de tipo a tipos delegados, use System.Delegate como o tipo de restrição. Por exemplo, altere where T : delegate para where T : System.Delegate.

O exemplo a seguir mostra a ordenação de restrição correta:

using System;

// Primary constraint first, then interface constraints, then new()
class C<T> where T : class, IDisposable, new() { }

// struct doesn't need new() - it's implicit
class D<T> where T : struct, IComparable { }

// Delegate constraint using System.Delegate
class E<T> where T : System.Delegate { }

Para obter mais informações, consulte Restrições em parâmetros de tipo.

Contagem e utilização de argumentos de tipo

Os seguintes erros referem-se ao fornecimento do número correto e do tipo de argumentos de tipo para tipos e métodos genéricos:

  • CS0224: um método com vararg não pode ser genérico, estar em um tipo genérico ou ter um parâmetro params.
  • CS0305: o uso do tipo genérico requer argumentos de tipo N.
  • CS0306: O tipo pode não ser usado como um argumento de tipo.
  • CS0307: O identificador não é um método genérico. Se você pretendia uma lista de expressões, use parênteses ao redor da expressão.
  • CS0308: O tipo ou método não genérico não pode ser usado com argumentos de tipo.
  • CS7002: uso inesperado de um nome genérico.

Para corrigir esses erros, verifique se você fornece o número exato de argumentos de tipo exigidos pela declaração genérica. Use apenas tipos válidos como argumentos de tipo. Não aplique argumentos de tipo a constructos não genéricos:

  • Remova parâmetros de tipo genérico ou que contenham declarações de tipo genérico de métodos que usam __arglist (CS0224). A __arglist palavra-chave é incompatível com genéricos porque os mecanismos de runtime para lidar com listas de argumentos variáveis entram em conflito com a substituição de tipo necessária para parâmetros de tipo genérico. Essa restrição também se aplica à params palavra-chave quando usada em combinação com métodos genéricos ou métodos em tipos genéricos.
  • Forneça o número exato de argumentos de tipo especificados na declaração de tipo ou método genérico (CS0305). Cada parâmetro de tipo genérico declarado na definição deve ter um argumento de tipo correspondente quando o tipo genérico é instanciado. O compilador precisa saber qual tipo concreto substituir para cada parâmetro de tipo. Por exemplo, se uma classe for declarada como class MyList<T>, você deverá fornecer exatamente um argumento de tipo ao usá-la, como MyList<int>, não MyList<int, string>.
  • Use apenas tipos válidos como argumentos de tipo (CS0306). Tipos de ponteiro, como int* ou char*, não podem ser usados como argumentos de tipo porque tipos genéricos exigem tipos gerenciados que o coletor de lixo pode rastrear e os tipos de ponteiro não são gerenciados. Se você precisar trabalhar com ponteiros em um contexto genérico, considere usar IntPtr ou reestruturar seu código para evitar misturar genéricos com código não seguro.
  • Remova a sintaxe de argumento de tipo de constructos não genéricos (CS0307, CS0308). Argumentos de tipo entre colchetes angulares (como <int>) só podem ser aplicados a tipos genéricos e métodos que declaram parâmetros de tipo. Você deve remover totalmente os argumentos de tipo ou garantir que importou o namespace que contém a versão genérica do tipo. Por exemplo, IEnumerator<T> requer a using System.Collections.Generic; diretiva, enquanto IEnumerator está em System.Collections.
  • Remova parâmetros de tipo de declarações que não dão suporte a genéricos (CS7002). Alguns constructos, como enumerações, não podem ser genéricos. Se você precisar de um contêiner genérico para valores de enum, considere usar uma classe ou struct genérica.

Para obter mais informações, consulte Parâmetros de tipo genérico e genéricos.

Restrições do construtor

Os seguintes erros estão relacionados à restrição new() em parâmetros de tipo genérico:

  • CS0304: Não é possível criar uma instância do tipo de variável porque ela não tem a new() restrição.
  • CS0310: O tipo deve ser um tipo não abstrato com um construtor público sem parâmetros para usá-lo como parâmetro no tipo ou método genérico.
  • CS0417: Identificador: não é possível fornecer argumentos ao criar uma instância de um tipo de variável.

Para corrigir esses erros, adicione a new() restrição aos parâmetros de tipo que precisam ser instanciados, verifique se os argumentos de tipo têm construtores públicos sem parâmetros e evite passar argumentos ao construir instâncias de parâmetros de tipo:

  • Adicione a new() restrição à declaração de parâmetro de tipo (CS0304). Quando você usa o new operador para criar uma instância de um parâmetro de tipo dentro de um tipo ou método genérico, o compilador deve ser capaz de garantir que qualquer argumento de tipo fornecido no runtime tenha um construtor sem parâmetros disponível. A new() restrição fornece essa garantia em tempo de compilação, permitindo que o compilador gere o código de instanciação apropriado. Por exemplo, se você tiver class C<T> com um membro T t = new T();, deverá alterar a declaração para class C<T> where T : new().
  • Verifique se os argumentos de tipo usados com new() parâmetros de tipo restrito têm construtores públicos sem parâmetros (CS0310). Quando um tipo ou método genérico declara uma new() restrição em um parâmetro de tipo, qualquer tipo concreto usado como argumento de tipo deve ser não abstrato e deve fornecer um construtor público sem parâmetros. Se um tipo tiver apenas construtores não públicos (como private ou protected construtores) ou tiver apenas construtores com parâmetros, ele não poderá satisfazer a new() restrição. Para corrigir esse erro, adicione um construtor público sem parâmetros ao tipo ou use um argumento de tipo diferente que já tenha um.
  • Remova argumentos de construtor ao instanciar parâmetros de tipo (CS0417). A new() restrição só garante a existência de um construtor sem parâmetros, portanto, você não pode passar argumentos para new T(arguments) porque o compilador não pode verificar se existe um construtor com esses tipos de parâmetros específicos nos tipos que são substituídos por T. Se você precisar construir instâncias com argumentos específicos, considere usar métodos de fábrica, padrões de fábrica abstratos ou restrições de classe base ou interface específicas que definem o comportamento de construção necessário.

Para obter mais informações, consulte Restrições nos parâmetros de tipo e a new() restrição.

Satisfação de restrições e conversões de processos

Os seguintes erros estão relacionados a argumentos de tipo que não satisfazem as restrições de parâmetros de tipo genérico:

  • CS0311: O tipo não pode ser usado como parâmetro T de tipo no tipo genérico ou método. Não há nenhuma conversão de referência implícita.
  • CS0312: O tipo não pode ser usado como parâmetro de tipo no tipo ou método genérico. O tipo anulável não atende à restrição.
  • CS0313: O tipo não pode ser usado como parâmetro de tipo no tipo ou método genérico. O tipo anulável não atende à restrição. Tipos que permitem valor nulo não podem atender a nenhuma restrição de interface.
  • CS0314: O tipo não pode ser usado como parâmetro de tipo em um tipo ou método genérico. Não há conversão de boxing ou de parâmetro de tipo.
  • CS0315: O tipo não pode ser usado como parâmetro T de tipo no tipo genérico ou método TypeorMethod<T>. Não há conversão de boxe.

Para corrigir esses erros, use argumentos de tipo que atendam a todas as restrições por meio de conversões apropriadas, garanta que as classes derivadas repitam restrições de classe base e entendam que os tipos de valor anuláveis têm requisitos de restrição especiais:

  • Altere o argumento de tipo para um que tenha uma conversão de referência implícita para o tipo de restrição (CS0311). Quando um parâmetro de tipo tem uma restrição como where T : BaseType, qualquer argumento de tipo deve ser conversível BaseType por meio de uma conversão de referência implícita ou conversão de identidade. O argumento de tipo deve ser BaseType ele mesmo, derivar de BaseType, ou implementar BaseType se for uma interface. Conversões numéricas implícitas (como de short para int) não satisfazem restrições de parâmetro de tipo genérico porque essas conversões são de valor, não de referência.
  • Repita as restrições de parâmetro de tipo da classe base em qualquer declaração de classe derivada (CS0314). Quando uma classe genérica derivada herda de uma classe genérica base que tem restrições em seus parâmetros de tipo, a classe derivada deve declarar as mesmas restrições em seus parâmetros de tipo correspondentes. Você deve repetir essas restrições porque o compilador precisa verificar se os argumentos de tipo fornecidos para a classe derivada atendem aos requisitos da classe base. Por exemplo, se você tiver public class A<T> where T : SomeClass, qualquer classe derivada dela deverá ser declarada como public class B<T> : A<T> where T : SomeClass.
  • Use tipos de valor não anuláveis ou altere o tipo de restrição (CS0312, CS0313). Tipos de valor anuláveis (como int?) são distintos de seus tipos de valor subjacentes e não atendem às mesmas restrições. Não há conversão implícita entre int? e int. Tipos de valor anuláveis não podem satisfazer restrições de interface porque o wrapper anulável em si não implementa a interface, mesmo que o tipo de valor subjacente o faça. Para corrigir esses erros, use a forma não anulável do tipo de valor como o argumento de tipo ou ajuste sua restrição para aceitar object ou um tipo de referência anulável, se apropriado.
  • Verifique se os argumentos de tipo atendem ao tipo de referência ou às restrições de classe (CS0315). Quando um parâmetro de tipo é restrito a um tipo de classe (como where T : SomeClass exemplo), você não pode usar um tipo de valor (struct) como o argumento de tipo porque não existe uma conversão de boxing que satisfaça a relação de restrição. A restrição requer um tipo de referência que tenha uma relação de herança ou implementação com o tipo de restrição. Para resolver esse erro, altere o struct para uma classe se for semanticamente apropriado ou remova a restrição de classe se o tipo genérico puder trabalhar com tipos de valor.

Para obter mais informações, consulte Restrições em parâmetros de tipo e conversões implícitas.

Restrições de uso de tipo genérico

Os seguintes erros estão relacionados a restrições sobre como tipos genéricos podem ser usados:

  • CS0403: não é possível converter nulo em parâmetro de tipo porque ele pode ser um tipo de valor não anulável. Considere usar default(T) em vez disso.
  • CS0413: O parâmetro de tipo não pode ser usado com o as operador porque ele não tem uma restrição de tipo de classe nem uma restrição class .
  • CS0695: o tipo não pode implementar ambas as interfaces, pois elas podem se unificar para algumas substituições de parâmetro de tipo.
  • CS0698: um tipo genérico não pode derivar do tipo porque é uma classe de atributo.
  • CS8322: não é possível passar argumento com tipo dinâmico para função local genérica com argumentos de tipo inferidos.
  • CS9338: Acessibilidade inconsistente: o tipo é menos acessível que a classe.

Para corrigir esses erros, use default em vez de null para parâmetros de tipo não restritos, adicione restrições de classe ao usar o operador as, evite conflitos de unificação de interface, não crie atributos genéricos e verifique se os argumentos de tipo correspondem à visibilidade dos membros que os contêm.

  • Substitua null as atribuições por default(T) ou adicione uma class restrição (CS0403). Quando você atribui null a um parâmetro de tipo não restrito, o compilador não pode garantir que o argumento de tipo seja um tipo de referência que aceita valores null, pois ele pode ser um tipo de valor como int ou struct, que não pode ser null. Para resolver esse erro, use default(T), que fornece o valor padrão apropriado para qualquer tipo (nulo para tipos de referência, zero ou vazio para tipos de valor) ou adicione uma class restrição ao parâmetro de tipo se você precisar especificamente de semântica de tipo de referência e quiser permitir null atribuições.
  • Adicione uma restrição de tipo específica ou class ao usar o operador as (CS0413). O as operador executa uma conversão de tipo seguro que retorna null se a conversão falhar, mas esse comportamento é incompatível com tipos de valor porque os tipos de valor não podem ser null. Quando você usa as com um parâmetro de tipo não restrito, o compilador não pode garantir que o argumento de tipo não seja um tipo de valor, e, por isso, rejeita o código. Para corrigir esse erro, adicione uma class restrição ou uma restrição de tipo de referência específica (como where T : SomeClass) para garantir que o parâmetro de tipo seja sempre um tipo de referência que possa lidar corretamente com o null resultado de uma conversão com falha.
  • Evite implementar a mesma interface genérica várias vezes com parâmetros de tipo que possam unificar (CS0695). Quando uma classe implementa uma interface genérica várias vezes com parâmetros de tipo diferentes (como class G<T1, T2> : I<T1>, I<T2>), há o risco de que alguém possa instanciá-la com o mesmo tipo para ambos os parâmetros (G<int, int>), o que criaria um conflito porque a classe estaria efetivamente implementando I<int> duas vezes. Para resolver esse erro, implemente a interface apenas uma vez, reestruture os parâmetros de tipo para impedir a unificação ou use classes não genéricas separadas para diferentes especializações.
  • Remova parâmetros de tipo genérico das classes de atributo (CS0698).

    Observação

    Esse erro não é produzido nas versões atuais do C#, pois agora há suporte para atributos genéricos.

  • Especifique explicitamente argumentos de tipo ao passar valores dinâmicos para funções locais genéricas (CS8322). Quando você passa um dynamic argumento para uma função local genérica, o compilador não pode inferir argumentos de tipo porque o tipo real não é conhecido até o runtime. Para corrigir esse erro, especifique explicitamente o argumento de tipo (por exemplo), LocalFunc<int>(d)converta o valor dinâmico para o tipo esperado ou use uma variável não dinâmica.
  • Verifique se os argumentos de tipo usados em assinaturas públicas ou protegidas são pelo menos tão acessíveis quanto o membro que os usa (CS9338). Um membro genérico público ou protegido deve usar argumentos de tipo que sejam publicamente acessíveis. Caso contrário, o código externo não poderia referenciar ou usar corretamente a assinatura do membro. Por exemplo, se você tiver um public class Container<T> onde T é um tipo interno, os assemblies externos podem ver o Container mas não podem funcionar corretamente com ele porque não podem ver o T. Para corrigir esse erro, torne o argumento de tipo público ou ajuste a acessibilidade do membro que o utiliza para que corresponda à acessibilidade do argumento de tipo.

Para obter mais informações, consulte Restrições em parâmetros de tipo, expressões de valor padrão e Atributos.

Tipos de restrição válidos

Os seguintes erros estão relacionados ao uso de tipos inválidos como restrições em parâmetros de tipo genérico:

  • CS0405: restrição duplicada para o parâmetro de tipo.
  • CS0702: a restrição não pode ser uma classe especial.
  • CS0703: acessibilidade inconsistente: o tipo de restrição é menos acessível que a declaração.
  • CS0706: tipo de restrição inválido. Um tipo usado como uma restrição deve ser uma interface, uma classe não lacrada ou um parâmetro de tipo.
  • CS0717: static classas classes estáticas não podem ser usadas como restrições.

Uma restrição deve ser uma interface, uma classe não lacrada ou um parâmetro de tipo. Determinados tipos são inválidos como restrições devido ao seu significado especial no sistema de tipos .NET ou porque não podem ser herdados.

Para corrigir estes erros:

  • Remover restrições duplicadas (CS0405). Cada restrição só pode aparecer uma vez em uma cláusula de restrição. Se você tiver where T : I, I, remova a duplicata.
  • Não use classes especiais como restrições (CS0702). Os tipos Objecte ArrayValueType não podem ser usados como restrições. Cada tipo já deriva de Object, portanto, restringir a ele não fornece nenhum valor. Array e ValueType são tipos base abstratos que não podem ser herdados diretamente. Se você precisar de um comportamento semelhante à matriz, use IList<T> ou IEnumerable<T> em vez disso.
  • Verifique se os tipos de restrição são pelo menos tão acessíveis quanto o tipo genérico (CS0703). Um tipo genérico público não pode ter restrições usando tipos internos, pois o código externo não seria capaz de fornecer argumentos de tipo válidos. Torne o tipo de restrição público ou reduza a acessibilidade do tipo genérico.
  • Use apenas interfaces, classes não lacradas ou parâmetros de tipo como restrições (CS0706). Você não pode usar matrizes, classes lacradas, structs, enums ou outros tipos inválidos como restrições. Se você precisar de um comportamento específico, considere usar uma interface que os tipos desejados implementam.
  • Não use classes estáticas como restrições (CS0717). As classes estáticas não podem ser estendidas porque contêm apenas membros estáticos. Nenhum tipo pode existir que deriva de uma classe estática, tornando-a inútil como uma restrição. Em vez disso, use uma classe ou interface não estática.

O exemplo a seguir mostra tipos de restrição válidos:

public interface IMyInterface { }
public class MyBaseClass { }

// Valid: interface constraint
class A<T> where T : IMyInterface { }

// Valid: non-sealed class constraint
class B<T> where T : MyBaseClass { }

// Valid: type parameter constraint
class C<T, U> where T : U { }

Para obter mais informações, consulte Restrições em parâmetros de tipo.

Conflitos de restrição e dependências circulares

Os seguintes erros estão relacionados a conflitos entre restrições ou dependências circulares em declarações de restrição:

  • CS0454: dependência de restrição circular envolvendo o Parâmetro de Tipo 1 e o Parâmetro de Tipo 2.
  • CS0455: o parâmetro type herda restrições conflitantes.

As restrições não podem criar dependências circulares e os parâmetros de tipo não podem herdar restrições conflitantes que são impossíveis de satisfazer simultaneamente.

Para corrigir estes erros:

  • Remova as dependências de restrição circular (CS0454). Um parâmetro de tipo não pode depender direta ou indiretamente de si mesmo por meio de suas restrições. Por exemplo, where T : U where U : T cria uma dependência circular porque T depende U e U depende de T. Quebre o ciclo removendo uma das restrições.
  • Remova restrições herdadas conflitantes (CS0455). Um parâmetro de tipo não pode ser restrito a várias classes não relacionadas, pois o C# não dá suporte a herança de várias classes. Da mesma forma, ele não pode ser restrito a ambos struct e a um tipo de classe, pois essas restrições são mutuamente exclusivas. Reestruturar sua hierarquia de tipos ou remover uma das restrições conflitantes.

O exemplo a seguir mostra os problemas:

// CS0454: Circular dependency - T depends on U and U depends on T
class Circular<T, U> where T : U where U : T { }

// CS0455: Conflicting constraints - U can't derive from both B and B2
public class B { }
public class B2 { }
public class G<T> where T : B
{
    public class N<U> where U : B2, T { }
}

Para obter mais informações, consulte Restrições em parâmetros de tipo.

Variação de parâmetro de tipo

O erro a seguir refere-se a modificadores de variação em parâmetros de tipo genérico:

  • CS1961: Variação inválida: o parâmetro de tipo deve ser validamente variante no tipo.

Modificadores de variação (in para contravariância, out para covariância) controlam como você usa parâmetros de tipo em declarações de interface e delegado. Um parâmetro de tipo covariante (out) só pode aparecer em posições de saída (tipos de retorno), enquanto um parâmetro de tipo contravariante (in) só pode aparecer em posições de entrada (tipos de parâmetro).

Para corrigir este erro:

  • Use out (covariante) para parâmetros de tipo que aparecem apenas em tipos de retorno. A covariância permite que um tipo mais derivado seja usado em que um tipo menos derivado é esperado.
  • Use in (contravariante) para parâmetros de tipo que aparecem apenas em tipos de parâmetro. A contravariância permite que um tipo menos derivado seja usado em que um tipo mais derivado é esperado.
  • Remova o modificador de variação se o parâmetro de tipo precisar aparecer nas posições de entrada e saída.

O exemplo a seguir mostra o uso correto e incorreto de variação:

// Incorrect: out T can't appear in input position
interface IWrong<out T>
{
    void Method(T arg);  // CS1961
}

// Correct: out T only in output positions
interface ICovariant<out T>
{
    T GetValue();
}

// Correct: in T only in input positions
interface IContravariant<in T>
{
    void Process(T arg);
}

// No modifier needed for both input and output
interface IInvariant<T>
{
    T Transform(T arg);
}

Para obter mais informações, consulte Covariância e Contravariância em Genéricos.