2

I have a generic function static Log<T>(T Log). I would like to check type of T and decide what to do next.

This is what I got so far:

public static void Log<T>(T log)
{
    switch (typeof(log))
    { ... }
}

What am I doing wrong? My error is that typeof(log) doesnt work.

Nicolas Voron
  • 2,916
  • 1
  • 21
  • 35
gorgi93
  • 2,457
  • 8
  • 30
  • 53

4 Answers4

3

You need to ask the typeof T not log - and a switch must be on a primitive type (or a string) so look at the type Name or perhaps FullName

switch(typeof(T).Name){...}

you could also call GetType on the instance of T:

switch(log.GetType().Name){...}

Both would yield the same result

Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • Of course String is not primitive! :-) It's just a C# compiler feature. The compiler is actually replace the switch on the string with a dictionary ( Like in my answer ) which has a int as value and does a switch on the int. – Felix K. Oct 09 '12 at 13:34
  • 1
    @FelixK. Fixed (for the pedants out there ;)) – Jamiec Oct 09 '12 at 13:41
3
switch (expression)
{

}

expression = An integral or string type expression (From MSDN)

http://msdn.microsoft.com/en-us/library/06tc147t(v=vs.71).aspx

The typeof keyword returns neither of these. You can't use log.GetType() as you need to meet the criteria above of which Type isn't suitable.

To be on the safe side I would limit this to if statements with the corresponding types as this will achieve the same thing.

static void a<T>(T b)
{
  if (typeof(T) == typeof(B))
    Console.WriteLine("T is B");
  else if(typeof(T) == typeof(C))
    Console.WriteLine("T is C");
}

EDIT:

If you have for arguments sake you have:

  public class Vehicle 
  {
    public virtual int MoveVehicle() 
    {
       //Do Logic
       return 0;
    }
  }
  public class Car : Vehicle { }

And you want a generic method to move the Vehicle you could do something called generic type constraints

static void a<T>(T b) where T : Vehicle
{
    int newPosition = b.MoveVehicle();
}

http://msdn.microsoft.com/en-us/library/bb384067.aspx

T has to be a Vehicle now, so you have access to the methods in Vehicle. You can pass a car to the method and it will still be able to call the MoveVehicle method.

  a<Vehicle>(new Car());
LukeHennerley
  • 6,344
  • 1
  • 32
  • 50
  • And if I would want to call some function on T how could I do this? lets say I have class car and people both support whoAmI function, could I call b.whoAmI() inside this generic function ??? – gorgi93 Oct 09 '12 at 13:06
  • @gr33x93 See my edit and check if this suffices what you want to achieve. – LukeHennerley Oct 09 '12 at 13:16
2

use GetType function

  switch(log.GetType().ToString()) {....}

insted of typeof().

Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
0

Solution

You cannot make a switch on a System.Type and also you cannot do a typeof on a variable. What you can do is this:

static Dictionary<Type, TypeEnum> Types = new Dictionary<Type, TypeEnum>() { { typeof(TypeA), TypeEnum.TypeA } }; // Fill with more key-value pairs

enum TypeEnum
{
    TypeA
    // Fill with types
}


public static void Log<T>(T log)
{
    TypeEnum type;
    if (Types.TryGetValue(typeof(T), out type)) {
        switch (type)
        { ... }
    }
}

It's also the fastest solution which i know. Dictionary lookups are very fast. You could also do this with a System.String ( via Type.Name or Type.FullName ) but it'll be slower because the string methods for Equals ( sure ) and for GetHashCode ( depending on their implementation ) are slower.

When you would use a String instead, it's the same what the compiler does when working with switch on a String.

switch(typeof(T).FullName) // Converted into a dictionary lookup
{ ... }

More thoughts

Depending on what you want to archive you should know that you also can use constraints:

public interface ILogItem
{
    String GetLogData();
    LogType LogType { get; }
}

public void Log<T>(T item) 
    where T : ILogItem
{
    Debug.WriteLine(item.GetLogData());
    // Read more data
    switch (item.LogType)
    { ... }
}
Felix K.
  • 6,201
  • 2
  • 38
  • 71