Restrição de tipo não gerenciadoUnmanaged type constraint

ResumoSummary

O recurso de restrição não gerenciado fornecerá a imposição de linguagem para a classe de tipos conhecida como "tipos não gerenciados" na especificação da linguagem C#. Isso é definido na seção 18,2 como um tipo que não é um tipo de referência e não contém campos de tipo de referência em nenhum nível de aninhamento.The unmanaged constraint feature will give language enforcement to the class of types known as "unmanaged types" in the C# language spec. This is defined in section 18.2 as a type which is not a reference type and doesn't contain reference type fields at any level of nesting.

MotivaçãoMotivation

A principal motivação é facilitar o autor do código de interoperabilidade de nível baixo no C#.The primary motivation is to make it easier to author low level interop code in C#. Os tipos não gerenciados são um dos principais blocos de construção do código de interoperabilidade, mas a falta de suporte em genéricos torna impossível criar rotinas reutilizáveis em todos os tipos não gerenciados.Unmanaged types are one of the core building blocks for interop code, yet the lack of support in generics makes it impossible to create re-usable routines across all unmanaged types. Em vez disso, os desenvolvedores são forçados a criar o mesmo código de placa para cada tipo não gerenciado em sua biblioteca:Instead developers are forced to author the same boiler plate code for every unmanaged type in their library:

int Hash(Point point) { ... } 
int Hash(TimeSpan timeSpan) { ... } 

Para habilitar esse tipo de cenário, o idioma apresentará uma nova restrição: não gerenciado:To enable this type of scenario the language will be introducing a new constraint: unmanaged:

void Hash<T>(T value) where T : unmanaged
{
    ...
}

Essa restrição só pode ser atendida por tipos que se encaixam na definição de tipo não gerenciado na especificação da linguagem C#. Outra maneira de observar isso é que um tipo satisfaz a restrição não gerenciada se ela também pode ser usada como um ponteiro.This constraint can only be met by types which fit into the unmanaged type definition in the C# language spec. Another way of looking at it is that a type satisfies the unmanaged constraint if it can also be used as a pointer.

Hash(new Point()); // Okay 
Hash(42); // Okay
Hash("hello") // Error: Type string does not satisfy the unmanaged constraint

Os parâmetros de tipo com a restrição não gerenciada podem usar todos os recursos disponíveis para tipos não gerenciados: ponteiros, fixos, etc...Type parameters with the unmanaged constraint can use all the features available to unmanaged types: pointers, fixed, etc ...

void Hash<T>(T value) where T : unmanaged
{
    // Okay
    fixed (T* p = &value) 
    { 
        ...
    }
}

Essa restrição também possibilitará ter conversões eficientes entre dados estruturados e fluxos de bytes.This constraint will also make it possible to have efficient conversions between structured data and streams of bytes. Essa é uma operação que é comum em pilhas de rede e camadas de serialização:This is an operation that is common in networking stacks and serialization layers:

Span<byte> Convert<T>(ref T value) where T : unmanaged 
{
    ...
}

Essas rotinas são vantajosas porque são provavelmente seguras no tempo de compilação e na alocação gratuita.Such routines are advantageous because they are provably safe at compile time and allocation free. Os autores de interoperabilidade atualmente não podem fazer isso (embora seja em uma camada em que o desempenho é crítico).Interop authors today can not do this (even though it's at a layer where perf is critical). Em vez disso, eles precisam contar com a alocação de rotinas que têm verificações de tempo de execução caras para verificar se os valores estão corretamente não gerenciados.Instead they need to rely on allocating routines that have expensive runtime checks to verify values are correctly unmanaged.

Design detalhadoDetailed design

O idioma apresentará uma nova restrição chamada unmanaged .The language will introduce a new constraint named unmanaged. Para atender a essa restrição, um tipo deve ser uma struct e todos os campos do tipo devem se enquadrar em uma das seguintes categorias:In order to satisfy this constraint a type must be a struct and all the fields of the type must fall into one of the following categories:

  • Ter o tipo,,,,,,, sbyte byte short ushort int uint long ulong , char , float , double , decimal , bool IntPtr ou UIntPtr .Have the type sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, IntPtr or UIntPtr.
  • Ser qualquer enum tipo.Be any enum type.
  • Ser um tipo de ponteiro.Be a pointer type.
  • Ser um struct definido pelo usuário que satisfaça a unmanaged restrição.Be a user defined struct that satisfies the unmanaged constraint.

Os campos de instância gerados pelo compilador, como os que fazem backup das propriedades implementadas automaticamente, também devem atender a essas restrições.Compiler generated instance fields, such as those backing auto-implemented properties, must also meet these constraints.

Por exemplo:For example:

// Unmanaged type
struct Point 
{ 
    int X;
    int Y {get; set;}
}

// Not an unmanaged type
struct Student 
{ 
    string FirstName;
    string LastName;
}

A unmanaged restrição não pode ser combinada com struct , class ou new() .The unmanaged constraint cannot be combined with struct, class or new(). Essa restrição deriva do fato que unmanaged implica struct , portanto, as outras restrições não fazem sentido.This restriction derives from the fact that unmanaged implies struct hence the other constraints do not make sense.

A unmanaged restrição não é imposta pelo CLR, somente pelo idioma.The unmanaged constraint is not enforced by CLR, only by the language. Para evitar o uso incorretamente por outras linguagens, os métodos que têm essa restrição serão protegidos por um mod-req. Isso impedirá que outras linguagens usem argumentos de tipo que não sejam tipos não gerenciados.To prevent mis-use by other languages, methods which have this constraint will be protected by a mod-req. This will prevent other languages from using type arguments which are not unmanaged types.

O token unmanaged na restrição não é uma palavra-chave nem uma palavra-chave contextual.The token unmanaged in the constraint is not a keyword, nor a contextual keyword. Em vez disso, é como se var ele fosse avaliado nesse local e também:Instead it is like var in that it is evaluated at that location and will either:

  • Associar ao tipo de usuário definido ou referenciado chamado unmanaged : isso será tratado assim que qualquer outra restrição de tipo nomeado for tratada.Bind to user defined or referenced type named unmanaged: This will be treated just as any other named type constraint is treated.
  • Associar a nenhum tipo: isso será interpretado como a unmanaged restrição.Bind to no type: This will be interpreted as the unmanaged constraint.

No caso de haver um tipo chamado unmanaged e está disponível sem qualificação no contexto atual, não haverá nenhuma maneira de usar a unmanaged restrição.In the case there is a type named unmanaged and it is available without qualification in the current context, then there will be no way to use the unmanaged constraint. Isso paraleliza as regras que envolvem o recurso var e os tipos definidos pelo usuário com o mesmo nome.This parallels the rules surrounding the feature var and user defined types of the same name.

DesvantagensDrawbacks

A principal desvantagem desse recurso é que ele atende a um pequeno número de desenvolvedores: normalmente, autores ou estruturas de biblioteca de nível baixo.The primary drawback of this feature is that it serves a small number of developers: typically low level library authors or frameworks. Portanto, está gastando um tempo de linguagem precioso para um pequeno número de desenvolvedores.Hence it's spending precious language time for a small number of developers.

Ainda assim, essas estruturas são a base para a maioria dos aplicativos .NET.Yet these frameworks are often the basis for the majority of .NET applications out there. Portanto, o desempenho/exatidão WINS nesse nível pode ter um efeito de ondulação no ecossistema do .NET.Hence performance / correctness wins at this level can have a ripple effect on the .NET ecosystem. Isso faz com que o recurso valha a pena considerar mesmo com o público limitado.This makes the feature worth considering even with the limited audience.

AlternativasAlternatives

Há algumas alternativas a serem consideradas:There are a couple of alternatives to consider:

  • O status quo: o recurso não é justificado em seus próprios méritos e os desenvolvedores continuam a usar o comportamento de consentimento implícito.The status quo: The feature is not justified on its own merits and developers continue to use the implicit opt in behavior.

PerguntasQuestions

Representação de metadadosMetadata Representation

A linguagem F # codifica a restrição no arquivo de assinatura, o que significa que o C# não pode usar novamente sua representação.The F# language encodes the constraint in the signature file which means C# cannot re-use their representation. Será necessário escolher um novo atributo para essa restrição.A new attribute will need to be chosen for this constraint. Além disso, um método que tem essa restrição deve ser protegido por um mod-req.Additionally a method which has this constraint must be protected by a mod-req.

Blittable versus não gerenciadoBlittable vs. Unmanaged

A linguagem F # tem um recurso muito semelhante que usa a palavra-chave unmanaged.The F# language has a very similar feature which uses the keyword unmanaged. O nome blittable é proveniente do uso em Midori.The blittable name comes from the use in Midori. Talvez você queira verificar a precedência aqui e usar não gerenciado.May want to look to precedence here and use unmanaged instead.

Resolução A linguagem decide usar não gerenciadoResolution The language decide to use unmanaged

VerificaçãoVerifier

O verificador/tempo de execução precisa ser atualizado para entender o uso de ponteiros para parâmetros de tipo genérico?Does the verifier / runtime need to be updated to understand the use of pointers to generic type parameters? Ou pode simplesmente funcionar como está sem alterações?Or can it simply work as is without changes?

Resolução Nenhuma alteração é necessária.Resolution No changes needed. Todos os tipos de ponteiro simplesmente não são verificáveis.All pointer types are simply unverifiable.

Criar reuniõesDesign meetings

N/Dn/a