Esto es lo que he encontrado.
Creo que no hay duda de que los nombres son legales a nivel binario en COM, ya que el nombre de una interfaz COM es su IID y el nombre del texto es solo documentación.
En el lado de .NET, la especificación relevante es la especificación de Common Language Infrastructure (ECMA-335, http://www.ecma-international.org/publications/standards/Ecma-335.htm). Me pregunto si .NET o Mono agregarán sus propias restricciones en la parte superior; hacerlo reduciría la interoperabilidad, pero esto es el mundo real
La sección 8.5.1 cubre nombres de tipos válidos en el sistema de tipos comunes, y simplemente dice que los nombres se comparan usando puntos de código. Es extraño que no diga nada sobre la composición de un nombre, solo cómo se comparan los nombres. Esta sección está parafraseada por MSDN en http://msdn.microsoft.com/en-us/library/exy17tbw%28v=VS.85%29.aspx, que dice que las únicas dos restricciones son (1) nombres de tipo "codificados como cadenas de caracteres Unicode (16 bits)" y (2) no pueden contener un 0x0000 incrustado.
He citado el bit sobre Unicode de 16 bits, en lugar de parafrasearlo, porque usa un lenguaje impreciso. Presumiblemente, el autor de esa página significaba UTF-16. En cualquier caso, ECMA-335 especifica la comparación byte por byte, y no hace mención de Unicode (con respecto a los nombres de tipo), y tampoco prohíbe los ceros incrustados. Quizás .NET se haya desviado del CTS aquí, aunque lo dudo. Lo más probable es que el autor de esta página de MSDN pensara en los lenguajes de programación cuando lo escribió.
La especificación de lenguaje común (también definida en ECMA-335) define las reglas para los identificadores en el código fuente. Los identificadores no son directamente relevantes para mi pregunta porque mis nombres de tipo internos nunca aparecen en el código fuente, pero lo analicé de inmediato. El CLS es un subconjunto del CTS, y como tal sus restricciones no son necesariamente parte del CTS más amplio. La Regla 4 de CLS dice que los identificadores deben seguir las reglas del Anexo 7 del Informe Técnico 15 del Estándar Unicode 3.0 - ver http://www.unicode.org/reports/tr15/tr15-18.html. Ese documento también es un poco vago, ya que se refiere a "otra letra" y "signos de puntuación del conector", pero no los define. Esto ayudó: http://notes.jschutz.net/topics/unicode/.
La sección 8.5.1 de la especificación ECMA incluye una nota no normativa de que un consumidor de CLS (como C# o el explorador de tipo Visual Studio, supongo) "no necesita consumir tipos que violen la regla 4 de CLS". los nombres de interfaz infringen esta Regla 4. Esta nota parece implicar que un tipo válido puede tener un nombre que viola la regla 4, y que un consumidor de CLS debe aceptar el nombre falso o ignorarlo de forma segura. (El navegador de tipo Visual Studio lo muestra sin quejarse).
Por lo tanto, mis nombres de tipos propuestos son generalmente ilegales en el código fuente. Pero tenga en cuenta que la sección 10.1 (sobre identificadores en el CLS) dice "Dado que sus reglas se aplican solo a los artículos exportados a otros idiomas, los miembros privados o no exportados desde un ensamblado pueden usar cualquier nombre que elijan"
¡Concluyo que es seguro usar los personajes # @! en mis nombres de tipo siempre y cuando permanezcan en el dominio binario y nunca tengan que aparecer en el código fuente ni fuera del ensamblaje. Y, de hecho, nunca se usan fuera del servidor COM.
Una palabra sobre el futuro-proofing ... El CTS prácticamente no tiene nada que decir sobre la composición de los nombres de los tipos, a pesar de tener una sección llamada "Nombres válidos" (sección 8.5.1). Podrían cambiar eso en el futuro, pero esta especificación amplia y liberal nos ha invitado a todos a hacer lo que nos gusta. Si los diseñadores de CTS hubieran querido dejar espacio para el cambio, seguramente habrían incorporado alguna provisión para eso, o al menos hubieran sido menos generosos.
Buena pregunta porque demuestra minuciosidad. Me gustan las preguntas como esta porque significa que al menos algunos programadores intentan anticipar problemas con anticipación. –