Partilhar via


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

Este artigo aborda os seguintes erros do compilador:

  • CS0080: Não são permitidas restrições em declarações não genéricas.
  • CS0081: A declaração do parâmetro de tipo deve ser um identificador, não um tipo.
  • CS0224: Um método com vararg não pode ser genérico, ser de tipo genérico ou ter um parâmetro params.
  • CS0304: Não é possível criar uma instância do tipo variável porque não tem a new() restrição.
  • CS0305: Usar o tipo genérico requer argumentos do tipo N.
  • CS0306: O tipo não pode ser usado como argumento de tipo.
  • CS0307: O identificador não é um método genérico. Se pretendia uma lista de expressões, use parênteses à volta 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 poder ser usado 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 existe conversão de referência implícita do tipo 1 para o tipo 2.
  • CS0312: O tipo 'tipo1' não pode ser usado como parâmetro de tipo no tipo genérico ou método. O tipo anulável 'tipo1' não satisfaz a restrição.
  • CS0313: O tipo 'tipo1' não pode ser usado como parâmetro de tipo no tipo genérico ou método. O tipo anulável 'tipo1' não satisfaz a restrição. Tipos anuláveis não conseguem satisfazer quaisquer restrições de interface.
  • CS0314: O tipo não pode ser usado como parâmetro de tipo no tipo genérico ou método. Não existe conversão para boxing nem conversão de parâmetros 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 para 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 pode ser um tipo de valor não anulável. Considera usar default(T) em vez disso.
  • CS0405: Restrição duplicada para o parâmetro de tipo.
  • CS0412: Parâmetro: um parâmetro, variável local ou 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 não tem uma restrição de tipo de classe nem uma class restrição.
  • CS0417: Identificador: não pode fornecer argumentos ao criar uma instância de um tipo de variável.
  • CS0449: As classrestrições , 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 pode especificar ambos uma classe de restrição e a restrição class ou struct.
  • CS0451: A new() restrição não pode ser usada com a struct restrição.
  • CS0454:Dependência circular de restrições envolvendo o Parâmetro de Tipo 1 e o Parâmetro de Tipo 2.
  • CS0455:O parâmetro de tipo herda restrições conflitantes.
  • CS0694: O parâmetro de tipo tem o mesmo nome que o tipo ou método que contém.
  • CS0695: T não pode implementar ambas as interfaces porque podem unificar-se para algumas substituições de parâmetros de tipos.
  • CS0698: Um tipo genérico não pode derivar do tipo porque é uma classe de atributo.
  • CS0702: A restrição não pode ser de classe especial.
  • CS0703: Acessibilidade inconsistente: o tipo de restrição é menos acessível do que a declaração.
  • CS0706: Tipo de restrição inválido. Um tipo usado como restrição deve ser uma interface, uma classe não selada ou um parâmetro de tipo.
  • CS0717: Classe estática: classes estáticas não podem ser usadas como restrições.
  • CS1961: Variância inválida: O parâmetro de tipo deve ser validamente variante do tipo.
  • CS7002: Uso inesperado de um nome genérico.
  • CS8322: Não é possível passar argumentos com tipo dinâmico para uma função local genérica com argumentos de tipo inferido.
  • CS9011: Palavra-chave delegate não pode ser usada como restrição. Querias dizer System.Delegate?
  • CS9012: Palavra-chave record inesperada. Queria dizer record struct ou record class?
  • CS9338: Acessibilidade inconsistente: o tipo é menos acessível do que a classe.

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

Os seguintes erros relacionam-se com a forma como declara e nomeia parâmetros de tipo em tipos e métodos genéricos:

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

Para corrigir estes erros, certifique-se de declarar parâmetros de tipo com identificadores válidos, aplicar cláusulas de restrição apenas a declarações genéricas e evitar conflitos de nomeação com outros identificadores no âmbito:

  • 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 e métodos genéricos que declaram parâmetros de tipo, porque as restrições definem requisitos que os argumentos de tipo devem satisfazer. Se você precisar aplicar restrições, primeiro adicione parâmetros de tipo à sua 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). Deve declarar parâmetros de tipo usando identificadores (como T, , ou TKey) em vez de tipos concretos (como TValue ou intstring). O objetivo de um parâmetro de tipo é servir como um marcador que o compilador substitui por tipos reais quando o tipo ou método genérico é utilizado. 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). Os nomes de parâmetros 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. Tais conflitos criam ambiguidade sobre qual identificador está sendo referenciado. Por exemplo, se você tiver um método public void F<T>(), você não pode declarar uma variável double T local dentro desse método, e você não pode nomear um parâmetro de tipo o mesmo que seu tipo de contenção (class C<C>).
  • Use a sintaxe correta de declaração de registo (CS9012). Ao declarar um tipo de registo, deve usar ou record class ou record struct (ou apenas record para um tipo de referência). A record palavra-chave sozinha não pode aparecer em posições onde o compilador espera uma sintaxe de declaração de tipo. Por exemplo, se queria declarar um tipo de registo, escreva record class MyRecord ou record struct MyRecord em vez de colocar record onde se espera uma palavra-chave diferente.

Para obter mais informações, consulte Generic Type Parameters and Generics.

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

Os seguintes erros relacionam-se com a sintaxe e ordenação das restrições em parâmetros genéricos de tipo:

  • CS0401: A new() restrição deve ser a última restrição especificada.
  • CS0449: As classrestrições , 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 pode especificar ambos, uma classe de restrição e as restrições class ou struct simultaneamente.
  • CS0451: A new() restrição não pode ser usada com a struct restrição.
  • CS9011: Palavra-chave delegate não pode ser usada como restrição. Querias dizer System.Delegate?

As restrições sobre os parâmetros do tipo devem seguir uma ordem específica: as restrições primárias (class, struct, unmanaged, notnull ou default) vêm primeiro, seguidas pelas restrições de interface ou de classe e, finalmente, a restrição do construtor new(). 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). Pode especificar no máximo um de class, struct, unmanaged, notnull, ou default, e deve aparecer primeiro na lista de restrições. As restrições class e struct são mutuamente exclusivas, assim como o são class e unmanaged. Num contexto anulável, class já implica notnull, por isso não podem ser combinados.
  • Não combines uma restrição específica de classe com struct (CS0450). Se um parâmetro de tipo está restrito a um tipo de classe específico, é implicitamente um tipo de referência, o que contradiz a struct restrição. Remova ou a restrição de classe ou a struct restrição.
  • Não combines new() com struct (CS0451). Todos os tipos de valores (structs) têm implicitamente um construtor público sem parâmetros, pelo que 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 de delegados, não como uma restrição. Para restringir um parâmetro de tipo a delegar tipos, use System.Delegate como tipo de restrição. Por exemplo, altere where T : delegate para where T : System.Delegate.

O exemplo seguinte mostra a ordem correta das restrições:

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 em programação

Os seguintes erros estão relacionados ao fornecimento do número e tipo corretos de argumentos de tipo para tipos e métodos genéricos:

  • CS0224: Um método com vararg não pode ser genérico, ser de tipo genérico ou ter um parâmetro params.
  • CS0305: Usar o tipo genérico requer argumentos do tipo N.
  • CS0306: O tipo não pode ser usado como argumento de tipo.
  • CS0307: O identificador não é um método genérico. Se pretendia uma lista de expressões, use parênteses à volta 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, certifique-se de fornecer 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 construções não genéricas:

  • Remova parâmetros de tipo genéricos ou que contenham declarações de tipo genéricas de métodos que usam __arglist (CS0224). A __arglist palavra-chave é incompatível com genéricos porque os mecanismos de tempo de execução para manipular listas de argumentos variáveis entram em conflito com a substituição de tipo necessária para parâmetros de tipo genéricos. Esta restrição também se aplica à params palavra-chave quando usada em combinação com métodos genéricos ou métodos dentro de tipos genéricos.
  • Forneça o número exato de argumentos de tipo especificados na declaração genérica de tipo ou método (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 , não MyList<int>MyList<int, string>.
  • Use apenas tipos válidos como argumentos de tipo (CS0306). Os tipos de ponteiro, como int* ou char*, não podem ser usados como argumentos de tipo porque os 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 inseguro.
  • Remova a sintaxe do argumento de tipo de construções não genéricas (CS0307, CS0308). Os argumentos de tipo entre colchetes angulares (como <int>) só podem ser aplicados a tipos e métodos genéricos que declaram parâmetros de tipo. Você deve remover completamente 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.
  • Remover parâmetros de tipo das declarações que não suportam genéricos (CS7002). Alguns construtos, como os enums, não podem ser genéricos. Se precisares de um contêiner genérico para valores de enum, considera usar uma classe ou uma struct genérica.

Para obter mais informações, consulte Generic Type Parameters and Generics.

Restrições do construtor

Os seguintes erros estão relacionados com a restrição em parâmetros de tipo genéricos new().

  • CS0304: Não é possível criar uma instância do tipo variável porque 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 poder ser usado como parâmetro no tipo ou método genérico.
  • CS0417: Identificador: não pode 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, certifique-se de que os argumentos de tipo tenham 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 type dentro de um tipo ou método genérico, o compilador deve ser capaz de garantir que qualquer argumento type fornecido em tempo de execução 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();, você deve alterar a declaração para class C<T> where T : new().
  • Certifique-se de que os argumentos de tipo usados com new() parâmetros de tipo restritos tenham construtores públicos sem parâmetros (CS0310). Quando um tipo ou método genérico declara uma new() restrição em um parâmetro tipo, qualquer tipo concreto usado como um argumento tipo não deve ser abstrato e deve fornecer um construtor sem argumentos público. Se um tipo tiver apenas construtores não públicos (como private construtores ou protected construtores) ou só tiver construtores com parâmetros, não pode satisfazer a new() restrição. Para corrigir este erro, pode adicionar um construtor público sem parâmetros ao tipo ou usar um argumento de tipo diferente que já tenha um.
  • Remova os argumentos do construtor ao instanciar parâmetros de tipo (CS0417). A new() restrição apenas garante a existência de um construtor sem parâmetros, por isso não pode passar argumentos a new T(arguments) porque o compilador não pode verificar que existe um construtor com esses tipos específicos de parâmetros nos tipos que substituem por T. Se precisares de construir instâncias com argumentos específicos, considera usar métodos de fábrica, padrões abstratos de fábrica, ou restrições específicas de classe base ou interface que definam o comportamento de construção de que precisas.

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

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

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

  • CS0311:O tipo não pode ser usado como parâmetro T de tipo no tipo genérico ou método. Não existe conversão implícita de referências.
  • CS0312: O tipo não pode ser usado como parâmetro de tipo no tipo genérico ou método. O tipo nulo não satisfaz a restrição.
  • CS0313: O tipo não pode ser usado como parâmetro de tipo no tipo genérico ou método. O tipo nulo não satisfaz a restrição. Tipos anuláveis não conseguem satisfazer quaisquer restrições de interface.
  • CS0314: O tipo não pode ser usado como parâmetro de tipo no tipo genérico ou método. Não existe conversão para boxing nem conversão de parâmetros 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 para boxe.

Para corrigir esses erros, use argumentos de tipo que satisfaçam todas as restrições por meio de conversões apropriadas, certifique-se de que as classes derivadas repitam as restrições de classe base e entenda que os tipos de valor nulo têm requisitos de restrição especiais:

  • Altere o argumento type 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 convertível em BaseType por meio de uma conversão de referência implícita ou conversão de identidade. O argumento do tipo deve ser BaseType ele próprio, 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 genéricas de parâmetros de tipo 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. Deve repetir estas restrições porque o compilador precisa de verificar que os argumentos de tipo fornecidos à classe derivada satisfaz os requisitos da classe base. Por exemplo, se você tiver public class A<T> where T : SomeClass, então qualquer classe derivada dele deve 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). Os tipos de valor anulável (como int?) são distintos de seus tipos de valor subjacentes e não satisfazem as mesmas restrições. Não há conversão implícita entre int? e int, e os tipos de valor anulável não podem satisfazer as 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 type ou ajuste sua restrição para aceitar object ou um tipo de referência anulável, se apropriado.
  • Certifique-se de que os argumentos de tipo satisfaçam as restrições de tipo ou classe de referência (CS0315). Quando um parâmetro de tipo é restrito a um tipo de classe (como where T : SomeClass), não se pode usar um tipo de valor (struct) como argumento de tipo porque não há conversão de encaixotamento 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 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 referem-se a restrições sobre a forma como os tipos genéricos podem ser utilizados:

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

Para corrigir esses erros, use default em vez de parâmetros de tipo sem restrições, adicione restrições de null classe ao usar o as operador, evite conflitos de unificação de interface, não crie classes de atributos genéricas e garanta que os argumentos de tipo correspondam à visibilidade de seus membros que os contêm:

  • Substituir null as atribuições por default(T) ou adicionar uma class restrição (CS0403). Quando você atribui null a um parâmetro de tipo sem restrições, o compilador não pode garantir que o argumento type seja um tipo de referência que aceite null valores, porque 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 type se precisar especificamente de semântica de tipo de referência e quiser permitir null atribuições.
  • Adicione uma restrição de class tipo ou específica ao usar o as operador (CS0413). O as operador executa uma conversão de tipo segura 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 sem restrições, o compilador não pode garantir que o argumento type não seja um tipo de valor, portanto, ele 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 type seja sempre um tipo de referência que possa manipular corretamente 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 poderiam 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á um 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 seus parâmetros de tipo para evitar a unificação ou use classes não genéricas separadas para especializações diferentes.
  • Remova parâmetros de tipo genéricos de classes de atributo (CS0698).

    Observação

    Este erro não é produzido nas versões atuais do C#, pois atributos genéricos são agora suportados.

  • Especifique explicitamente argumentos de tipo ao passar valores dinâmicos para funções locais genéricas (CS8322). Quando passa um dynamic argumento para uma função local genérica, o compilador não pode inferir argumentos de tipo porque o tipo real só é conhecido em tempo de execução. Para corrigir este erro, especifique explicitamente o argumento do tipo (por exemplo, LocalFunc<int>(d)), conjure 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 público ou genérico protegido deve usar argumentos de tipo que sejam acessíveis publicamente. Caso contrário, o código externo não poderia referenciar ou usar corretamente a assinatura do membro. Por exemplo, se tiver public class Container<T> onde T é um tipo interno, os assemblies externos podem ver o Container, mas não conseguem trabalhar corretamente com ele porque não conseguem ver T. Para corrigir esse erro, torne o argumento type público ou reduza a acessibilidade do membro que o usa para corresponder à acessibilidade do argumento type.

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

Tipos de restrições válidos

Os seguintes erros relacionam-se com o uso de tipos inválidos como restrições em parâmetros genéricos de tipo:

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

Uma restrição deve ser uma interface, uma classe não selada ou um parâmetro de tipo. Certos 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 numa cláusula de restrição. Se tiver where T : I, I, remove o duplicado.
  • Não uses classes especiais como restrições (CS0702). Os tipos Object, Array, e ValueType não podem ser usados como restrições. Todo tipo já deriva de Object, por isso restringir-se a ele não fornece valor. Array e ValueType são tipos base abstratos que não podem ser herdados diretamente. Se precisares de comportamento semelhante a um array, usa IList<T> ou IEnumerable<T> em vez disso.
  • Garantir que os tipos de restrições 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, porque código externo não conseguiria fornecer argumentos de tipo válidos. Ou torna o tipo de restrição público, ou reduz a acessibilidade do tipo genérico.
  • Use apenas interfaces, classes não seladas ou parâmetros de tipo como restrições (CS0706). Não podes usar arrays, classes seladas, structs, enums ou outros tipos inválidos como restrições. Se precisar de comportamentos específicos, considere usar uma interface que os tipos desejados implementem.
  • Não uses classes estáticas como restrições (CS0717). As classes estáticas não podem ser estendidas porque só contêm membros estáticos. Nenhum tipo pode existir que derive de uma classe estática, tornando-o inútil como restrição. Use antes uma classe ou interface não estática.

O exemplo seguinte mostra tipos de restrições 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ções e dependências circulares

Os seguintes erros relacionam-se com conflitos entre restrições ou dependências circulares em declarações de restrições:

  • CS0454:Dependência circular de restrições envolvendo o Parâmetro de Tipo 1 e o Parâmetro de Tipo 2.
  • CS0455:O parâmetro de tipo 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:

  • Remover dependências circulares de restrições (CS0454). Um parâmetro de tipo não pode depender direta ou indiretamente de si próprio através das suas restrições. Por exemplo, where T : U where U : T cria uma dependência circular porque T depende de U e U depende de T. Quebra o ciclo removendo uma das restrições.
  • Remover restrições herdadas conflitantes (CS0455). Um parâmetro de tipo não pode ser limitado a múltiplas classes não relacionadas, porque C# não suporta herança múltipla de classes. De forma semelhante, não pode ser restringido a ambos struct e a um tipo de classe, pois estas restrições são mutuamente exclusivas. Reestrutura a hierarquia de tipos ou remove uma das restrições conflitantes.

O exemplo seguinte 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.

Variância do parâmetro de tipo

O seguinte erro relaciona-se com modificadores de variância em parâmetros genéricos de tipo:

  • CS1961: Variância inválida: O parâmetro de tipo deve ser validamente variante do tipo.

Modificadores de variância (in para contravariância, out para covariância) controlam como usas os parâmetros de tipo na interface e delegam declarações. 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 só aparecem nos tipos de retorno. A covariância permite usar um tipo mais derivado onde se espera um tipo menos derivado.
  • Use in (contravariante) para parâmetros de tipo que só aparecem nos tipos de parâmetros. A contravariância permite usar um tipo menos derivado onde se espera um tipo mais derivado.
  • Remova o modificador de variância se o parâmetro de tipo tiver de aparecer tanto nas posições de entrada como de saída.

O exemplo seguinte mostra o uso correto e incorreto da variância:

// 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 mais informações, veja Covariância e Contravariância em Genéricos.