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.
Você pode usar o ref modificador na declaração de um tipo de estrutura. As instâncias de um ref struct tipo são alocadas na pilha e não podem escapar para o heap gerenciado. Para garantir isso, o compilador limita o uso de ref struct tipos da seguinte maneira:
- A
ref structnão pode ser o tipo de elemento de uma matriz. - A
ref structnão pode ser um tipo declarado de um campo de uma classe ou um não-ref struct. - A
ref structnão pode ser encaixotado para System.ValueType ou System.Object. - Uma
ref structvariável não pode ser capturada em uma expressão lambda ou em uma função local. - Antes do C# 13,
ref structas variáveis não podiam ser usadas em umasyncmétodo. A partir do C# 13, umaref structvariável não pode ser usada no mesmo bloco que aawaitexpressão em umasyncmétodo. No entanto, você pode usarref structvariáveis em métodos síncronos, por exemplo, em métodos que retornam Task ou Task<TResult>. - Antes do C# 13, uma
ref structvariável não podia ser usada em iteradores. A partir do C# 13,ref structtipos ereflocais podem ser usados em iteradores, desde que não estejam em segmentos de código com ayield returninstrução. - Antes do C# 13, um
ref structnão pode implementar interfaces. A partir do C# 13, umrefstruct pode implementar interfaces, mas deve aderir às regras de segurança ref. Por exemplo, umref structtipo não pode ser convertido para o tipo de interface porque isso requer uma conversão de boxe. - Antes do C# 13, um
ref structnão pode ser um argumento de tipo. A partir de C# 13, aref structpode ser o argumento type quando o parâmetro type especifica oallows ref structem suawherecláusula.
Normalmente, você define um ref struct tipo quando precisa de um tipo que também inclui membros de dados de ref struct tipos:
public ref struct CustomRef
{
public bool IsValid;
public Span<int> Inputs;
public Span<int> Outputs;
}
Para declarar a ref struct como readonly, combine os readonly modificadores e ref na declaração de tipo (o readonly modificador deve vir antes do ref modificador):
public readonly ref struct ConversionRequest
{
public ConversionRequest(double rate, ReadOnlySpan<double> values)
{
Rate = rate;
Values = values;
}
public double Rate { get; }
public ReadOnlySpan<double> Values { get; }
}
No .NET, exemplos de um ref struct são System.Span<T> e System.ReadOnlySpan<T>.
ref campos
Pode declarar um ref campo em , ref structcomo mostra o exemplo seguinte:
public ref struct RefFieldExample
{
private ref int number;
public int GetNumber()
{
if (System.Runtime.CompilerServices.Unsafe.IsNullRef(ref number))
{
throw new InvalidOperationException("The number ref field is not initialized.");
}
return number;
}
}
Um ref campo pode ter o null valor. Use o Unsafe.IsNullRef<T>(T) método para determinar se um ref campo é null.
Você pode aplicar o readonly modificador a um ref campo das seguintes maneiras:
-
readonly ref: Você pode ref reatribuir tal campo com o operador apenas dentro de= refum construtor ou uminitacessador. Você pode atribuir um valor com o=operador em qualquer ponto permitido pelo modificador de acesso ao campo. -
ref readonly: A qualquer momento, você não pode atribuir um valor com o=operador a esse campo. No entanto, você pode ref reatribuir um campo com o= refoperador. -
readonly ref readonly: Você só pode ref reatribuir tal campo em um construtor ou acessadorinit. A qualquer momento, não é possível atribuir um valor ao campo.
O compilador garante que uma referência armazenada em um ref campo não sobreviva ao seu referente.
O ref recurso de campos permite uma implementação segura de tipos como System.Span<T>:
public readonly ref struct Span<T>
{
internal readonly ref T _reference;
private readonly int _length;
// Omitted for brevity...
}
O Span<T> tipo armazena uma referência através da qual ele acessa os elementos contíguos na memória. O uso de uma referência permite que uma Span<T> instância evite copiar o armazenamento ao qual se refere.
O padrão descartável
Você pode definir um descartável ref struct. Para fazer isso, certifique-se de que um ref struct se encaixa no padrão descartável. Ou seja, ele tem um método de instância Dispose que é acessível, sem parâmetros e tem um void tipo de retorno. Você pode usar a instrução using ou declaração com uma instância de um descartável ref struct.
A partir do C# 13, você também pode implementar os IDisposable tipos on ref struct . No entanto, a resolução de sobrecarga prefere o padrão descartável ao método de interface. O compilador resolve para um IDisposable.Dispose método somente quando um método adequado Dispose não é encontrado.
Restrições para ref struct tipos que implementam uma interface
Essas restrições garantem que um ref struct tipo que implementa uma interface obedeça às regras de segurança de referência necessárias.
- Um
ref structnão pode ser convertido em uma instância de uma interface que ele implementa. Essa restrição inclui a conversão implícita quando você usa umref structtipo como argumento quando o parâmetro é um tipo de interface. A conversão resulta em uma conversão de boxe, o que viola a segurança de ref. Umref structpode declarar métodos como declarações de interface explícitas. No entanto, esses métodos só podem ser acessados a partir de métodos genéricos onde o parâmetro de tipoallows ref structé utilizado. - Um
ref structque implementa uma interface deve implementar todos os membros da interface da instância. Oref structdeve implementar membros da instância mesmo quando a interface inclui uma implementação padrão.
O compilador impõe essas restrições. Se você escrever ref struct tipos que implementam interfaces, cada nova atualização pode incluir novos membros de interface padrão. Até forneceres uma implementação para quaisquer novos métodos de instância, a tua aplicação não compila. Não é possível fornecer uma implementação específica para um método de interface static com uma implementação padrão.
Importante
A ref struct que implementa uma interface inclui o potencial para alterações posteriores de quebra de código-fonte e de quebra binária. A quebra ocorre se a ref struct implementar uma interface definida noutra assembleia, e essa montagem fornecer uma atualização que adiciona membros por defeito a essa interface.
A quebra de origem acontece quando você recompila o ref struct: Ele deve implementar o novo membro, mesmo que haja uma implementação padrão.
A quebra binária acontece se você atualizar o assembly externo sem recompilar o ref struct tipo e o código atualizado chamar a implementação padrão do novo método. O tempo de execução lança uma exceção quando o membro padrão é acessado.
Especificação da linguagem C#
Para obter mais informações, consulte as seguintes seções da especificação da linguagem C#:
Para obter mais informações sobre ref campos, consulte a nota da proposta de melhorias de estrutura de baixo nível.