开发者

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

开发者 https://www.devze.com 2023-01-18 20:22 出处:网络
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

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开发者_Go百科#?

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.


This is not possible.


As others mentioned what you want to do isn't going to work, but, you can look at what types of objects you want to support and limit it to some class/interface that they have in common, or you may just need to ditch the generic part and write several extension methods, so you can disallow 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 e.g. 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消