2011-12-15 4 views
18

Al definir las restricciones de un parámetro de tipo genérico, tenemos que poner class() al frente y new() al final, por ejemplo.¿Por qué se aplica algún pedido en restricciones de parámetros genéricos?

¿Por qué es esto? ¿Por qué no puedo poner mis restricciones en cualquier orden?

¿Hay alguna otra restricción en el pedido además de class/struct primero, new() al final?


Ejemplo:

protected T Clone<T>() where T : class, ICopyable<T>, new() 
+6

Como fondo, la especificación del lenguaje establece que las restricciones deben estar en el orden * restricción primaria, restricción secundaria, restricción del constructor *, donde una * restricción primaria * es simplemente * clase * o * estructura *, una * restricción secundaria * es una interfaz dada o tipo de clase, y la * restricción del constructor * es simplemente la * nueva() *. En cuanto a por qué están clasificados como tales y requieren ese orden, no tengo ni idea. Tal vez la especificación del lenguaje anotado arroje algo de luz sobre él? –

+0

Interesante, gracias. Es por eso que estoy particularmente interesado en. –

Respuesta

23

No hay ninguna razón particular por qué se eligió ese orden. El orden elegido va de más general a más específico, lo que supongo que es una propiedad razonablemente agradable.

En cuanto a la pregunta "¿por qué requieren un pedido?", Es simplemente más fácil para los equipos de implementación y prueba tener un orden claro e inequívoco impuesto por el idioma. Podríamos permitir que las restricciones entren en cualquier orden, pero ¿qué nos compra eso?

Cuanto más trabajo en idiomas, más opino que cada vez que le da una opción al usuario, les da la oportunidad de hacer una mala elección. Un principio básico del diseño de C# es que le decimos cuándo las cosas se ven mal y le obligamos a corregirlas, lo cual no es un principio básico de diseño de, por ejemplo, JavaScript. Su principio básico de diseño es "mezclarse en todo e intentar hacer lo que el usuario quiso decir". Al colocar más restricciones en la sintaxis correcta en C# podemos garantizar mejor que la semántica prevista se expresa bien en el programa.

Por ejemplo, si estuviera diseñando un # lenguaje -como C Hoy no hay manera de que iba a tener sintaxis ambiguos como:

class C : X , Y 

o

... where T : X, Y 

Y tiene la clara intención de ser una interfaz. Es X? No podemos decir sintácticamente si X tenía la intención de ser una interfaz o una clase. Basta con decir que esta ambigüedad complica en gran medida cosas como la detección de ciclos en tipos básicos frente a interfaces, etc. Sería mucho más fácil para todos los interesados ​​si fuera más detallado, como lo es en VB.

+1

+1 Gracias por tomarse el tiempo para proporcionar una idea del tipo de decisiones que se toman y por qué. –

+2

Siempre me pareció extraño que C# exprese herencia e implemente interfaces de manera diferente a Java (que lo hace explícitamente), cuando C# está muy influenciado por Java en la mayoría de los demás aspectos. Es aún más extraño dado que, como dices, complica los trabajos de los compiladores. – MgSam

+0

"más fácil para los equipos de implementación y prueba" ... eso me sorprende. Aunque la implementación de una gramática más pequeña es probablemente un poco más fácil, ahora tiene toda una función adicional para implementar y probar: "Generar un error cuando el orden es incorrecto" –

1

Como la mayoría de las preguntas relacionadas con la sintaxis, la respuesta básica es porque la especificación así lo dice. Obtenemos la siguiente gramática para las restricciones de tipo genérico de la especificación C# 5.0 (Sección 10.1.5)

tipo de parámetros-restricciones:

primary-constraint 
secondary-constraints 
constructor-constraint 
primary-constraint , secondary-constraints 
primary-constraint , constructor-constraint 
secondary-constraints , constructor-constraint 
primary-constraint , secondary-constraints , constructor-constraint 

primaria-restricción:

class-type 
class 
struct 

secundarios-restricciones:

interface-type 
type-parameter 
secondary-constraints , interface-type 
secondary-constraints , type-parameter 

constructor de restricción:

new ( ) 

Eric Lippert ha hecho un excelente trabajo de explicar por qué se ha diseñado de esta manera, por lo que no voy a exponer sobre eso.

Cuestiones relacionadas