interface (Referência C#)
Uma interface define um contrato. Qualquer class
, record
ou struct
que implemente esse contrato deve fornecer uma implementação dos membros definidos na interface. Uma interface pode definir uma implementação padrão para membros. Também pode definir static
membros, a fim de fornecer uma implementação única para a funcionalidade comum. A partir do C# 11, uma interface pode definir static abstract
ou static virtual
membros para declarar que um tipo de implementação deve fornecer os membros declarados. Normalmente, static virtual
os métodos declaram que uma implementação deve definir um conjunto de operadores sobrecarregados.
No exemplo a seguir, a classe ImplementationClass
deve implementar um método chamado SampleMethod
que não tem parâmetros e retorna void
.
Para obter mais informações e exemplos, consulte Interfaces.
Uma interface de nível superior, declarada em um namespace, mas não aninhada dentro de outro tipo, pode ser declarada public
ou internal
. A predefinição é internal
. As declarações de interface aninhadas, aquelas declaradas dentro de outro tipo, podem ser declaradas usando qualquer modificador de acesso.
Os membros da interface sem uma implementação não podem incluir um modificador de acesso. Membros com uma implementação padrão podem incluir qualquer modificador de acesso.
Exemplo de interface
interface ISampleInterface
{
void SampleMethod();
}
class ImplementationClass : ISampleInterface
{
// Explicit interface member implementation:
void ISampleInterface.SampleMethod()
{
// Method implementation.
}
static void Main()
{
// Declare an interface instance.
ISampleInterface obj = new ImplementationClass();
// Call the member.
obj.SampleMethod();
}
}
Uma interface pode ser um membro de um namespace ou uma classe. Uma declaração de interface pode conter declarações (assinaturas sem qualquer implementação) dos seguintes membros:
Membros da interface padrão
Essas declarações de membro anteriores normalmente não contêm um corpo. Um membro da interface pode declarar um organismo. Os órgãos membros em uma interface são a implementação padrão. Membros com corpos permitem que a interface forneça uma implementação "padrão" para classes e estruturas que não fornecem uma implementação de substituição.
Importante
Adicionar membros de interfaces padrão força qualquer ref struct
um que implemente a interface a adicionar uma declaração explícita desse membro.
Uma interface pode incluir:
- Constantes
- Operadores
- Construtor estático.
- Tipos aninhados
- Campos, métodos, propriedades, indexadores e eventos estáticos
- Declarações de membro usando a sintaxe de implementação de interface explícita.
- Modificadores de acesso explícito (o acesso padrão é
public
).
Membros estáticos abstratos e virtuais
A partir do C# 11, uma interface pode declarar static abstract
e static virtual
membros para todos os tipos de membros, exceto campos. As interfaces podem declarar que os tipos de implementação devem definir operadores ou outros membros estáticos. Esse recurso permite que algoritmos genéricos especifiquem um comportamento semelhante a um número. Você pode ver exemplos nos tipos numéricos no tempo de execução do .NET, como System.Numerics.INumber<TSelf>. Essas interfaces definem operadores matemáticos comuns que são implementados por muitos tipos numéricos. O compilador deve resolver chamadas e static abstract
métodos em static virtual
tempo de compilação. Os static virtual
métodos e static abstract
declarados em interfaces não têm um mecanismo de despacho de tempo de execução análogo ou virtual
abstract
métodos declarados em classes. Em vez disso, o compilador usa informações de tipo disponíveis em tempo de compilação. Portanto, static virtual
os métodos são quase exclusivamente declarados em interfaces genéricas. Além disso, a maioria das interfaces que declaram static virtual
ou static abstract
métodos declaram que um dos parâmetros de tipo deve implementar a interface declarada. Por exemplo, a INumber<T>
interface declara que T
deve implementar INumber<T>
. O compilador usa o argumento type para resolver chamadas para os métodos e operadores declarados na declaração de interface. Por exemplo, o int
tipo implementa INumber<int>
. Quando o parâmetro T
type indica o argumento int
type , os membros declarados static
em int
são invocados. Como alternativa, quando double
é o argumento type, os membros declarados double
static
no tipo são invocados.
Importante
O envio de métodos para static abstract
e static virtual
métodos declarados em interfaces é resolvido usando o tipo de tempo de compilação de uma expressão. Se o tipo de tempo de execução de uma expressão for derivado de um tipo de tempo de compilação diferente, os métodos estáticos no tipo base (tempo de compilação) serão chamados.
Você pode tentar esse recurso trabalhando com o tutorial sobre membros abstratos estáticos em interfaces.
Herança de interface
As interfaces não podem conter o estado da instância. Embora os campos estáticos agora sejam permitidos, os campos de instância não são permitidos nas interfaces. As propriedades automáticas de instância não são suportadas em interfaces, pois elas declarariam implicitamente um campo oculto. Esta regra tem um efeito subtil nas declarações de propriedade. Em uma declaração de interface, o código a seguir não declara uma propriedade implementada automaticamente como em um class
ou struct
. Em vez disso, ele declara uma propriedade que não tem uma implementação padrão, mas deve ser implementada em qualquer tipo que implemente a interface:
public interface INamed
{
public string Name {get; set;}
}
Uma interface pode herdar de uma ou mais interfaces base. Quando uma interface herda de outra interface, um tipo que implementa a interface derivada deve implementar todos os membros nas interfaces base, bem como aqueles declarados na interface derivada, conforme mostrado no código a seguir:
public interface I1
{
void M1();
}
public interface I2 : I1
{
void M2();
}
public class C : I2
{
// implements I1.M1
public void M1() { }
// implements I2.M2
public void M2() { }
}
Quando uma interface substitui um método implementado em uma interface base, ela deve usar a sintaxe explícita de implementação da interface.
Quando uma lista de tipos base contém uma classe base e interfaces, a classe base deve vir em primeiro lugar na lista.
Uma classe que implementa uma interface pode implementar explicitamente membros dessa interface. Um membro explicitamente implementado não pode ser acessado por meio de uma instância de classe, mas apenas por meio de uma instância da interface. Além disso, os membros da interface padrão só podem ser acessados por meio de uma instância da interface.
Para obter mais informações sobre a implementação de interface explícita, consulte Implementação de interface explícita.
Exemplo de implementação de interface
O exemplo a seguir demonstra a implementação da interface. Neste exemplo, a interface contém a declaração de propriedade e a classe contém a implementação. Qualquer instância de uma classe que implementa tem propriedades x
inteiras IPoint
e y
.
interface IPoint
{
// Property signatures:
int X { get; set; }
int Y { get; set; }
double Distance { get; }
}
class Point : IPoint
{
// Constructor:
public Point(int x, int y)
{
X = x;
Y = y;
}
// Property implementation:
public int X { get; set; }
public int Y { get; set; }
// Property implementation
public double Distance =>
Math.Sqrt(X * X + Y * Y);
}
class MainClass
{
static void PrintPoint(IPoint p)
{
Console.WriteLine("x={0}, y={1}", p.X, p.Y);
}
static void Main()
{
IPoint p = new Point(2, 3);
Console.Write("My Point: ");
PrintPoint(p);
}
}
// Output: My Point: x=2, y=3
Especificação da linguagem C#
Para obter mais informações, consulte a seção Interfaces da especificação da linguagem C#, a especificação de recurso para C# 8 - Membros de interface padrão e a especificação de recurso para C# 11 - membros abstratos estáticos em interfaces