2010-10-04 18 views
6

He desarrollado algunos métodos de extensión para objetos, que no quiero usar/mostrar en intellisense para objetos que implementen IEnumerable. Conceptualmente quiero algo como el siguiente¿Cómo se especifica un parámetro de tipo que NO implementa una interfaz en particular?

public static T SomeMethod<T>(this object value) where T != IEnumerable 
     { 

     } 

¿Es posible imponer este tipo de restricción de todos modos en C#?

Editar

Lo sentimos, puse la pregunta de una manera incorrecta. Conozco las restricciones permisibles en C#, lo que quiero saber es si hay alguna otra manera de lograr esto.

+0

Tiene cuatro tipos de restricciones sobre los genéricos en C#, y este no es uno de ellos. No creo que sea posible, pero alguien con más experiencia que yo debería confirmar esto. –

+0

Con IntelliSense, supongo que lo mejor que puede hacer es escribir un comentario de que este método no está disponible para los tipos que implementan IEnumerable. No es perfecto, pero es mejor que nada. –

Respuesta

13

Solo para confirmar el comentario de Øyvind: no hay tal restricción en C#. Los únicos tipos de restricción son:

  • where T : struct (no anulable tipo valor de restricción)
  • where T : class (tipo de referencia restricción)
  • where T : SomeClassName (conversión a una restricción de clase particular)
  • where T : ISomeInterfaceName (conversión a una restricción de interfaz particular)
  • where T : U (conversión a otra restricción de parámetro de tipo)
  • where T : new() (sin parámetros restricción constructor)

Tenga en cuenta que sólo he separa las limitaciones de clases e interfaces específicas ya que el primero es una limitación primaria y el último es una restricción secundaria.

+0

¿Hay alguna otra forma de atajo para lograr esto? –

+2

@Anindya: No hay forma de hacerlo en tiempo de compilación, corto o largo. Podrías lanzar una excepción en el momento de la ejecución, pero es bastante desagradable hacerlo. –

+1

bastante desagradable de hecho :) Y tampoco ayudará a su objetivo de eliminar el método de extensión de IntelliSense. –

0

Esto no es posible.

1

Esto no es compatible. Las restricciones legales se enumeran here.

0

Como otros mencionaron que lo que quiere hacer no va a funcionar, pero puede ver qué tipos de objetos desea admitir y limitarlo a alguna clase/interfaz que tienen en común, o puede solo necesita deshacerse de la parte genérica y escribir varios métodos de extensión, por lo que puede rechazar IEnumerable.

0

No puede, y estoy de acuerdo que es una molestia, aunque lo que he querido no es tanto lo que está buscando, sino que prevalece sobre la base de la restricción (para poder, por ejemplo, tener una clase y una versión de estructura del mismo método o clase, y tener el apropiado utilizado según corresponda).

Hay dos casos en los que podemos pasarlo bien.

Una es cuando nuestra razón para no querer que se use un método de extensión es que ya se proporciona como un método de instancia. De hecho, obtenemos esto gratis; siempre se utilizan métodos de instancia en lugar de métodos de extensión (aunque no se usará derivedClass.method() cuando llame al baseClass.method() si solo existe en derivedClass).

El otro caso es la selección de tiempo de ejecución:

public static T SomeMethod<T>(this object value) where T != IEnumerable 
{ 
    if(typeof(T).GetInterface("IEnumerable") != null) 
    { 
    //behaviour appropriate for IEnumerable 
    } 
    else 
    { 
    //other behaviour. 
    } 
} 

No es ideal, especialmente si la única "comportamiento apropiado para IEnumerable" es lanzar una excepción, pero puede ser suficiente a veces.

+0

¿Qué pasa con typeof (T) .GetInterface ("IEnumerable")! = Null. ¿Es o no más claro? –

+0

@Esben, tomado de mi pensamiento sobre otra cosa, donde tuve que lidiar con el tipo por separado del objeto. Sí, 'is'or' as' serviría bien y sería mucho más claro. –

0

Puede hacer algo como esto, pero solo para los tipos que controla.

decir que quiere tener un método como este:

public static class XmlSerializableExtension { 
    public static string ToXml(this object self) { 
    // ... 
    } 
} 

Pero no quieren contaminar todos los objetos con ella, sólo un subconjunto de sus clases.

Se puede lograr de esta manera:

public interface MXmlSerializable { } 
public static class XmlSerializable { 
    public static string ToXml(this MXmlSerializable self) { 
    // ... 
    } 
} 

Ahora, se marcan las clases que desea que este método se aplique a la "mixin" interfaz:

public class MyClass : MXmlSerializable { 
    // ... 
} 

Y sólo aparecerá en intellisense para estas clases.

Cuestiones relacionadas