简体   繁体   中英

How to specify a type parameter which does NOT implement a particular interface?

I have developed some extension methods for objects, which I don't want to be used/shown in intellisense for objects which implements IEnumerable. Conceptually I want something like as follows

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

        }

Is it possible to impose this kind of constraint anyway in C#?

Edit

Sorry, I put the question in a wrong way. I know the allowable constraints in C#, what I want to know is that if there is any other way to accomplish this?

Just to confirm Øyvind's comment: there's no such constraint in C#. The only types of constraint are:

  • where T : struct (non-nullable value type constraint)
  • where T : class (reference type constraint)
  • where T : SomeClassName (conversion to a particular class constraint)
  • where T : ISomeInterfaceName (conversion to a particular interface constraint)
  • where T : U (conversion to another type parameter constraint)
  • where T : new() (parameterless constructor constraint)

Note that I've only separated out the specific class and interface constraints as the former is a primary constraint and the latter is a secondary constraint.

This is not supported. Legal constraints are listed here .

这是不可能的。

正如其他人提到的那样,您想要做的事情行不通,但是,您可以查看要支持的对象类型并将其限制为它们共有的某些类/接口,或者您可能只需要放弃通用部分,并编写几种扩展方法,因此可以禁止IEnumerable。

You can't, and I agree it's a nuisance, though what I've found myself wanting is not so much what you are looking for, as overriding on the basis of the constraint (so that I could eg have a class and a struct version of the same method or class, and have the appropriate one used as applicable).

There are two cases where we can get by well.

One is where our reason for not wanting an extension method to be used is that it's already supplied as an instance method. In fact we get this for free; instance methods are always used instead of extension methods (though a derivedClass.method() wont' be used when you call baseClass.method() if it only exists in derivedClass ).

The other case is runtime selection:

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

It's not ideal, especially if the only "behaviour appropriate for IEnumerable" is to throw an exception, but it can be enough sometimes.

You can do something like this, but only for types that you control.

Say you want to have a method like this:

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

But you don't want to pollute every object with it, only a subset of your classes.

You can achieve it like this:

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

Now, you mark the classes that you want this method to apply to with the "mixin" interface:

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

And it will only appear in intellisense for these classes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM