Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Uma interface contém definições para um grupo de funcionalidades relacionadas que um não-abstrato class ou um struct deve implementar. Uma interface pode definir static métodos. Uma interface pode definir uma implementação padrão para membros. Uma interface não pode declarar dados de instância, como campos, propriedades implementadas automaticamente ou eventos semelhantes a propriedades.
Usando interfaces, você pode, por exemplo, incluir o comportamento de várias fontes em uma classe. Esse recurso é importante em C# porque a linguagem não suporta herança múltipla de classes. Além disso, você deve usar uma interface se quiser simular herança para structs, porque eles não podem realmente herdar de outro struct ou classe.
Você define uma interface usando a interface palavra-chave como mostra o exemplo a seguir.
interface IEquatable<T>
{
bool Equals(T obj);
}
O nome de uma interface deve ser um nome de identificador C# válido. Por convenção, os nomes das interfaces começam com maiúscula I.
Qualquer classe ou struct que implemente a IEquatable<T> interface deve conter uma definição para um Equals método que corresponda à assinatura especificada pela interface. Como resultado, você pode contar com uma classe de tipo T que implementa IEquatable<T> para conter um Equals método com o qual uma instância dessa classe pode determinar se é igual a outra instância da mesma classe.
A definição de IEquatable<T> não fornece uma implementação para Equals. Uma classe ou struct pode implementar várias interfaces, mas uma classe só pode herdar de uma única classe.
Para obter mais informações sobre classes abstratas, consulte Classes abstratas e seladas e Membros da classe.
As interfaces podem conter métodos de instância, propriedades, eventos, indexadores ou qualquer combinação desses quatro tipos de membros. As interfaces podem conter construtores, campos, constantes ou operadores estáticos. Membros de interface que não são campos podem ser static abstract. Uma interface não pode conter campos de instância, construtores de instância ou finalizadores. Os membros da interface são públicos por padrão, e você pode especificar explicitamente modificadores de acessibilidade, como public, protected, internal, private, protected internalou private protected. Um private membro deve ter uma implementação padrão.
Para implementar um membro da interface usando a implementação implícita, o membro correspondente da classe de implementação deve ser público, não estático e ter o mesmo nome e assinatura que o membro da interface. Deve usar implementação explícita de interface para implementar membros de interface que não sejam destinados a ser públicos.
Nota
Quando uma interface declara membros estáticos, um tipo que implementa essa interface também pode declarar membros estáticos com a mesma assinatura. Esses membros são distintos e identificados de forma única pelo tipo que os declara. O membro estático declarado em um tipo não substitui o membro estático declarado na interface.
Uma classe ou struct que implementa uma interface deve fornecer uma implementação para todos os membros declarados sem uma implementação padrão fornecida pela interface. No entanto, se uma classe base implementa uma interface, qualquer classe derivada da classe base herda essa implementação.
O exemplo a seguir mostra uma implementação da IEquatable<T> interface. A classe de implementação, Car, deve fornecer uma implementação do Equals método.
public class Car : IEquatable<Car>
{
public string? Make { get; set; }
public string? Model { get; set; }
public string? Year { get; set; }
// Implementation of IEquatable<T> interface
public bool Equals(Car? car)
{
return (this.Make, this.Model, this.Year) ==
(car?.Make, car?.Model, car?.Year);
}
}
Propriedades e indexadores de uma classe podem definir acessórios adicionais para uma propriedade ou indexador declarado numa interface. Por exemplo, uma interface pode declarar uma propriedade que tenha um acessador get . A classe que implementa a interface pode declarar a mesma propriedade com um get acessador e set . No entanto, se a propriedade ou indexador usa implementação explícita, os acessadores devem corresponder. Para obter mais informações sobre implementação explícita, consulte Implementação de interface explícita e propriedades da interface.
As interfaces podem herdar de uma ou mais interfaces. A interface derivada herda os membros de suas interfaces base. Uma classe que implementa uma interface derivada deve implementar todos os membros na interface derivada, incluindo todos os membros das interfaces base da interface derivada. Essa classe pode ser implicitamente convertida para a interface derivada ou qualquer uma de suas interfaces base. Uma classe pode incluir uma interface várias vezes através de classes base que herda ou através de interfaces que outras interfaces herdam. No entanto, a classe pode fornecer uma implementação de uma interface apenas uma vez e somente se a classe declarar a interface como parte da definição da classe (class ClassName : InterfaceName). Se a interface é herdada porque você herdou uma classe base que implementa a interface, a classe base fornece a implementação dos membros da interface. No entanto, a classe derivada pode reimplementar qualquer membro da interface virtual em vez de usar a implementação herdada. Quando as interfaces declaram uma implementação padrão de um método, qualquer classe que implemente essa interface herda essa implementação (Você precisa converter a instância de classe para o tipo de interface para acessar a implementação padrão no membro Interface).
Uma classe base também pode implementar membros da interface usando membros virtuais. Nesse caso, uma classe derivada pode alterar o comportamento da interface substituindo os membros virtuais. Para obter mais informações sobre membros virtuais, consulte Polimorfismo.
Trabalhando com interfaces internas
Uma interface interna normalmente pode ser implementada usando implementação implícita com membros públicos, desde que todos os tipos na assinatura da interface sejam acessíveis publicamente. No entanto, quando uma interface usa tipos internos em suas assinaturas de membro, a implementação implícita torna-se impossível porque o membro da classe de implementação precisaria ser público ao expor tipos internos. Nesses casos, você deve usar a implementação de interface explícita.
O exemplo a seguir mostra os dois cenários:
// Internal type that cannot be exposed publicly
internal class InternalConfiguration
{
public string Setting { get; set; } = "";
}
// Internal interface that CAN be implemented with public members
// because it only uses public types in its signature
internal interface ILoggable
{
void Log(string message); // string is public, so this works with implicit implementation
}
// Interface with internal accessibility using internal types
internal interface IConfigurable
{
void Configure(InternalConfiguration config); // Internal type prevents implicit implementation
}
// This class shows both implicit and explicit interface implementation
public class ServiceImplementation : ILoggable, IConfigurable
{
// Implicit implementation works for ILoggable because string is public
public void Log(string message)
{
Console.WriteLine($"Log: {message}");
}
// Explicit implementation required for IConfigurable because it uses internal types
void IConfigurable.Configure(InternalConfiguration config)
{
// Implementation here
Console.WriteLine($"Configured with: {config.Setting}");
}
// If we tried implicit implementation for IConfigurable, this wouldn't compile:
// public void Configure(InternalConfiguration config) // Error: cannot expose internal type
}
No exemplo anterior, a IConfigurable interface usa um tipo InternalConfiguration interno em sua assinatura de método. A classe ServiceImplementation não pode usar implementação implícita porque isso exigiria tornar o método Configure público, o que não é permitido quando a assinatura do método contém tipos internos. Em vez disso, a implementação de interface explícita é usada, que não tem um modificador de acesso e só é acessível através do tipo de interface.
Por outro lado, a ILoggable interface pode ser implementada implicitamente com membros públicos porque todos os tipos na sua assinatura (string) são acessíveis publicamente, mesmo que a interface em si seja interna.
Para obter mais informações sobre a implementação de interface explícita, consulte Implementação de interface explícita.
Resumo das interfaces
Uma interface tem as seguintes propriedades:
- Em versões C# anteriores à 8.0, uma interface é como uma classe base abstrata com apenas membros abstratos. Uma classe ou struct que implementa a interface deve implementar todos os seus membros.
- A partir do C# 8.0, uma interface pode definir implementações padrão para alguns ou todos os seus membros. Uma classe ou struct que implementa a interface não precisa implementar membros que tenham implementações padrão. Para obter mais informações, consulte métodos de interface padrão.
- Uma interface não pode ser instanciada diretamente.
- Uma classe ou struct pode implementar várias interfaces. Uma classe pode herdar uma classe base e também implementar uma ou mais interfaces.