开发者

Switch off of type [duplicate]

开发者 https://www.devze.com 2023-01-08 07:24 出处:网络
This question already has answers here: Closed 12 years ago. Possible Duplicate: Switch Case on type of object (C#)
This question already has answers here: Closed 12 years ago.

Possible Duplicate:

Switch Case on type of object (C#)

I have a method signature that looks like this:

    public static TLocalType ToLocalType<TLocalType, TContract>(TContract contract)
    {

I would li开发者_运维百科ke to be able to do different things based on the actual type of TContract (ie call different methods). Is there a way to do something like this?

        switch (TContract)
        {
             case SomeTypeHere:


Unfortunately, the best you can do is

switch(typeof(TContract).ToString()) 

Note that this includes namespaces. Note also that it will ignore inheritance and interfaces.

Peter Hallam explains why the language doesn't support this.


That's a fairly frequently requested feature which we are not going to do. See Peter Hallam's article on the subject for more details.

http://blogs.msdn.com/b/peterhal/archive/2005/07/05/435760.aspx

Note that if you are switching on the type of a generic then you probably have a design flaw somewhere. The whole point of generics is that they are generic; you shouldn't care what the actual type is.


How about using Polymorphism here? I can't speak to your exact situation, but typically, when you want to switch on the type of an object, that is a sign that you may want to consider a polymorphic solution.


You can't switch on the Type object, but you can switch on it's name:

switch( typeof(TContract).Name )
{
   case "Namespace.SomeTypeName": ...
}

In general, however, this rarely proves to be a good design choice. You are better off passing in a delegate or a object that implements an interface (or even a generic type parameter) to define the "strategies" for handling different types.

This is a common question about designing and writing generic types - namely the ability to perform entirely different actions based on the type of the generic type parameters. I tend to view this as a code smell that you may not be using generics as they were intended and your design is "going against the grain", so to speak.

However, in some cases it is indeed necessary to perform processing that varies by type, in which case passing in a separate type (either to the constructor as another generic parameter) allows you to separate the different concerns into "strategies" that are more extensible, cleaner, and less coupled to the implementation of the generic class. An example might be:

interface IOperation<T>
{
    T Add( T first, T second );
}

public class Calculator<T,TOp>
   where TOp : IOperation<T>, new()
{
    private readonly TOp m_Op = new TOp();

    public T Sum( IEnumerable<T> values )
    {
        T accum = default(T);
        foreach( var val in values )
            accum = m_Op( accum, val );
        return accum;
    }
}

Now you can write different implementations of IOperation<T> that are appropriate to different types (integers, floating point numbers, complex numbers, matrixes, etc). The generic class Calculator<T,TOp> is then separate from the operations that vary by type, but is free to compose them as it sees fit.

In .NET 4.0 it's possible to use dynamic to dispatch to overloads of one or more methods that are specialized for certain types. This approach, while simpler, incurs the performance penalty of essentially invoking the compiler at runtime to figure out which method to invoke. Althought, the DLR does to a reasonably good job of caching this information at the call site, which can amortize the cost if you will invoke the method multiple times.


The switch statement only accepts numeric and string values, which means that you can't use a Type value. You could switch off of the ToString() value of the type, but that's as close as you'll get. I would recommend using an enum instead.


Switch only works for strings and other primitives.

You'd have to do something like this, where you switch off the string name of the type:

switch (typeof(T).FullName)
{
  case "System.Int32":
    Console.WriteLine("it's an int");
    break;
  case "System.String":
    Console.WriteLine("it's a string");
    break;
  default:
    Console.WriteLine("not sure");
    break;
}
0

精彩评论

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

关注公众号