Restricción de tipo no administradoUnmanaged type constraint

ResumenSummary

La característica de restricción no administrada proporcionará el cumplimiento del lenguaje a la clase de tipos conocidos como "tipos no administrados" en la especificación del lenguaje C#. Esto se define en la sección 18,2 como un tipo que no es un tipo de referencia y no contiene campos de tipo de referencia en ningún nivel de anidamiento.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.

MotivaciónMotivation

La motivación principal es facilitar la creación de código de interoperabilidad de bajo nivel en C#.The primary motivation is to make it easier to author low level interop code in C#. Los tipos no administrados son uno de los bloques de creación principales del código de interoperabilidad, pero la falta de compatibilidad en genéricos hace que sea imposible crear rutinas reutilizables en todos los tipos no administrados.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. En su lugar, se obliga a los desarrolladores a crear el mismo código de placa de caldera para cada tipo no administrado en su 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 este tipo de escenario, el lenguaje introducirá una nueva restricción:To enable this type of scenario the language will be introducing a new constraint: unmanaged:

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

Esta restricción solo se puede cumplir a través de tipos que se ajustan a la definición de tipo no administrado en la especificación del lenguaje C#. Otra manera de examinarlo es que un tipo satisface la restricción no administrada si también se puede utilizar como puntero.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

Los parámetros de tipo con la restricción no administrada pueden usar todas las características disponibles para los tipos no administrados: punteros, fijos, 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) 
    { 
        ...
    }
}

Esta restricción también hará posible tener conversiones eficaces entre los datos estructurados y los flujos de bytes.This constraint will also make it possible to have efficient conversions between structured data and streams of bytes. Se trata de una operación que es habitual en las pilas de red y en las capas de serialización:This is an operation that is common in networking stacks and serialization layers:

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

Estas rutinas son ventajosas porque son provably seguras en tiempo de compilación y la asignación es gratuita.Such routines are advantageous because they are provably safe at compile time and allocation free. Los autores de interoperabilidad hoy no pueden hacerlo (aunque se encuentra en una capa en la que el rendimiento es crítico).Interop authors today can not do this (even though it's at a layer where perf is critical). En su lugar, deben confiar en la asignación de rutinas que tienen comprobaciones en tiempo de ejecución costosas para comprobar que los valores se han desadministrado correctamente.Instead they need to rely on allocating routines that have expensive runtime checks to verify values are correctly unmanaged.

Diseño detalladoDetailed design

El lenguaje introducirá una nueva restricción denominada unmanaged .The language will introduce a new constraint named unmanaged. Para satisfacer esta restricción, un tipo debe ser una estructura y todos los campos del tipo deben corresponder a una de las siguientes categorías: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:

  • Tienen el tipo sbyte ,,, byte short ushort , int , uint , long , ulong , char , float , double , decimal , bool IntPtr o UIntPtr .Have the type sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, IntPtr or UIntPtr.
  • Ser cualquier enum tipo.Be any enum type.
  • Ser un tipo de puntero.Be a pointer type.
  • Ser una estructura definida por el usuario que cumpla la unmanaged restricción.Be a user defined struct that satisfies the unmanaged constraint.

Los campos de instancia generados por el compilador, como los que respaldan las propiedades implementadas automáticamente, también deben cumplir estas restricciones.Compiler generated instance fields, such as those backing auto-implemented properties, must also meet these constraints.

Por ejemplo:For example:

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

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

La unmanaged restricción no se puede combinar con struct , class o new() .The unmanaged constraint cannot be combined with struct, class or new(). Esta restricción se deriva del hecho de que implica que, por lo unmanaged struct tanto, las demás restricciones no tienen sentido.This restriction derives from the fact that unmanaged implies struct hence the other constraints do not make sense.

unmanagedCLR no aplica la restricción, solo en el lenguaje.The unmanaged constraint is not enforced by CLR, only by the language. Para evitar que otros lenguajes lo utilicen, los métodos que tienen esta restricción estarán protegidos por mod-req. Esto impedirá que otros lenguajes usen argumentos de tipo que no son tipos no administrados.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.

El token unmanaged de la restricción no es una palabra clave ni una palabra clave contextual.The token unmanaged in the constraint is not a keyword, nor a contextual keyword. En su lugar, es como var en que se evalúa en esa ubicación y:Instead it is like var in that it is evaluated at that location and will either:

  • Enlazar a un tipo definido por el usuario o al que se hace referencia llamado unmanaged : se tratará como cualquier otra restricción de tipo con nombre que se trate.Bind to user defined or referenced type named unmanaged: This will be treated just as any other named type constraint is treated.
  • Enlazar a ningún tipo: se interpretará como la unmanaged restricción.Bind to no type: This will be interpreted as the unmanaged constraint.

En el caso de que haya un tipo denominado unmanaged y que esté disponible sin calificación en el contexto actual, no habrá forma de usar la unmanaged restricción.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. Esto se asemeja a las reglas que rodean la característica var y los tipos definidos por el usuario del mismo nombre.This parallels the rules surrounding the feature var and user defined types of the same name.

InconvenientesDrawbacks

El principal inconveniente de esta característica es que sirve a un pequeño número de desarrolladores: normalmente los autores o marcos de la biblioteca de bajo nivel.The primary drawback of this feature is that it serves a small number of developers: typically low level library authors or frameworks. Por lo tanto, se pierde un tiempo de lenguaje precioso para un pequeño número de desarrolladores.Hence it's spending precious language time for a small number of developers.

Sin embargo, estos marcos de trabajo suelen ser la base de la mayoría de las aplicaciones .NET.Yet these frameworks are often the basis for the majority of .NET applications out there. Por lo tanto, el rendimiento y la exactitud de WINS en este nivel pueden tener un efecto de rizo en el ecosistema de .NET.Hence performance / correctness wins at this level can have a ripple effect on the .NET ecosystem. Esto hace que la característica merezca la pena considerar incluso con la audiencia limitada.This makes the feature worth considering even with the limited audience.

AlternativasAlternatives

Hay un par de alternativas a tener en cuenta:There are a couple of alternatives to consider:

  • El estado quo: la característica no está justificada por sus propios méritos y los desarrolladores siguen usando el comportamiento de participación implícita.The status quo: The feature is not justified on its own merits and developers continue to use the implicit opt in behavior.

PreguntasQuestions

Representación de metadatosMetadata Representation

El lenguaje F # codifica la restricción en el archivo de signatura, lo que significa que C# no puede volver a usar su representación.The F# language encodes the constraint in the signature file which means C# cannot re-use their representation. Se debe elegir un nuevo atributo para esta restricción.A new attribute will need to be chosen for this constraint. Además, un método que tiene esta restricción debe estar protegido por mod-req.Additionally a method which has this constraint must be protected by a mod-req.

Bytes entre bits y no administradosBlittable vs. Unmanaged

El lenguaje F # tiene una característica muy similar que usa la palabra clave Unmanaged.The F# language has a very similar feature which uses the keyword unmanaged. El nombre que se va a representar como bits/bytes proviene del uso en Midori.The blittable name comes from the use in Midori. Puede que le interese buscar la precedencia aquí y usar en su lugar no administrada.May want to look to precedence here and use unmanaged instead.

Solución de El lenguaje que decide usar no administradoResolution The language decide to use unmanaged

ComprobadorVerifier

¿Es necesario actualizar el comprobador/tiempo de ejecución para comprender el uso de punteros a parámetros de tipo genérico?Does the verifier / runtime need to be updated to understand the use of pointers to generic type parameters? ¿O puede simplemente trabajar como está sin cambios?Or can it simply work as is without changes?

Solución de No se necesitan cambios.Resolution No changes needed. Todos los tipos de puntero son simplemente no comprobables.All pointer types are simply unverifiable.

Design MeetingsDesign meetings

N/Dn/a