views:

222

answers:

8

I want to associate custom data to a Type, and retrieve that data in run-time, blazingly fast.

This is just my imagination, of my perfect world:

var myInfo = typeof(MyClass).GetMyInformation();

this would be very fast... of course this does not exist! If it did I would not be asking. hehe ;)

This is the way using custom attributes:

var myInfo = typeof(MyClass).GetCustomAttribute("MyInformation");

this is slow because it requires a lookup of the string "MyInformation"

This is a way using a Dictionary<Type, MyInformation>:

var myInfo = myInformationDictionary[typeof(MyClass)];

This is also slow because it is still a lookup of 'typeof(MyClass)'.

I know that dictionary is very fast, but this is not enough... it is not as fast as calling a method. It is not even the same order of speed.

I am not saying I want it to be as fast as a method call. I want to associate information with a type and access it as fast as possible. I am asking whether there is a better way, or event a best way of doing it.

Any ideas??

Thanks!

EDIT:

The typeof(MyClass) I mentioned in all of previous snippets, are actualy variable... I don't know that it is a specific MyClass type, it could be any type:

Type myType = typeFromSomewhere;

i.e. MyClass in this case just says that the class is made by me, and any other types that could come into this situation is also made by me... so it reads

typeof( One of My Own Classes, that I don't know witch one is it, but it is mine for sure )

EDIT: CONCLUSION

Some performance results related to dictionaries:

Dic.buckets | Dic.Count | Dic.Key | Ops(x17)/s | Avg.Time | Min.Time | Max.Time
-----------------------------------------------------------------------------
     17519  |    12467  |   Type  |    1051538 |  0.95μs  |  0.86μs  |  0.42ms
       919  |      912  |   Type  |     814862 |  1.23μs  |  1.14μs  |  0.46ms
   1162687  |      912  |   Type  |    1126382 |  0.89μs  |  0.81μs  |  0.33ms
       919  |      912  |   Type  |     806992 |  1.24μs  |  1.16μs  |  0.21ms
        17  |       17  |   Type  |     872485 |  1.15μs  |  1.06μs  |  0.31ms
-----------------------------------------------------------------------------
     36353  |    18160  |  String |     227520 |  4.40μs  |  3.98μs  |  0.47ms
       919  |      911  |  String |     219159 |  4.57μs  |  4.14μs  |  0.29ms
   1162687  |      911  |  String |     236384 |  4.23μs  |  3.82μs  |  0.41ms
       919  |      911  |  String |     223042 |  4.49μs  |  4.10μs  |  0.43ms
        17  |       17  |  String |     229985 |  4.35μs  |  3.94μs  |  0.28ms

Interface Call:

ops(x17)/s: 2896001
Average: 0.35μs
Min: 0.34μs
Max: 1.20μs

Virtual Call:

ops(x17)/s: 3115254
Average: 0.32μs
Min: 0.32μs
Max: 0.65μs

I see that I have under-estimated Dictionaries!!! =)

It seems that Dictionary of Type to anything is 3x to 4x slower than a virtual method call.

This is not the case using Dictionary of strings. That ones are 10x to 12x slower than a virtual method call.

So I have prooved me wrong!

And, NO I AM NOT MAKING A MISSILE!!! someone has supposed this in a comment bellow =)

Thanks everybody.

+2  A: 

Declare static properties or methods on your type.

class YourType
{
  public static string GetMyInformation()
  {
    return "Some info on this type";
  }
}

Then you can access the data in your code as follows

var myInfo = YourType.GetMyInformation();

Or did I miss the point?

Chris Taylor
You missed the point in the fact that I have a Type variable: i.e. var myType = typeof(something)... the type is not one fixed type.
Miguel Angelo
@Miguel, ok sorry about that. I overlooked the important detail...
Chris Taylor
@Chris Taylor: Not your fault, I didn't mention that before... but I made it more clear now, I think!
Miguel Angelo
+5  A: 

It's not just your "perfect world", it's C# too! You can use extension methods to make precisely what you suggested work:

var myInfo = typeof(MyClass).GetMyInformation();

In a static TypeUtilities class or such, you would define the following:

public static InfoType GetMyInformation(this Type type)
{
    // Return InfoType object.
}

As to how you actually return the information on the type, that could be done in anumber of ways. A simple if-block, a static Dictionary, reflection on the given type (using attributes/methods), or even others. The best approach there depends very much on the context and your particular usage scenario.

Noldorin
But then, how do I implement diferent behaviour depending on the type. I would still have to look in a lookup table, or something.
Miguel Angelo
A dictionary or a simple if statement or even some reflection may be best depending on the scenario. Can you elaborate please?
Noldorin
I have solved my problem with a simple 4 buckests only structure to cache previously accessed items of the dictionary... now it is almost as fast as a method call, for most of the time... extension methods was not the case, I am just talking about performance. Thanks!
Miguel Angelo
No worries. However, might help to be a bit more specific about your *precise* problem next time in the original post. I think it was slightly misleading what you actually wanted. :)
Noldorin
A: 

write extension methods for System.Type that will do all such operations for you.

this. __curious_geek
+2  A: 

Um, how about you use a dictionary of Dictionary<string, MyInformation>:

You know they type you are looking for already by definition if you are using the typeof method. Instead, you could declare a const string MY_CLASS_TYPE_NAME = "MyNamespace.MyClass"

It's not the prettiest, but it's blazingly fast and doesn't limit your functionality.

MrGumbe
My tests showed me that using Dictionary of Types is the best thing to do.
Miguel Angelo
+2  A: 

Why not use GetCustomAttributes(typeof(MyInformationAttribute), false)?

IMHO, using attributes is the semantically correct way to express information like this. Just make sure you use a sealed attribute class, as that improves the runtime performance.

Though, it wouldn't be difficult, and would probably be preferable to either lazy-load or somehow otherwise cache the attribute instances. I generally do this once using a static field when the application is initialized.

Daniel Schaffer
This has no use for BCL types, however. Very limited in that respect.
Noldorin
I have tested all the ways using reflection and it is FOR SURE, the WORST way (talking about performance) of associating information with a Type. Anyway... thanks for trying!
Miguel Angelo
+4  A: 

Dictionary<Type,Object> works for me.

Sky Sanders
Indeed! I was wrong... my premise was based on some old tests that I barelly remembered. Tests done again, and posted!
Miguel Angelo
+4  A: 

If the type is statically available then consider using something like,

public class Data<T, V>
{
    public static V Info;
}

which is used like,

Data<int, string>.Info = "A string associated with int";
Data<string, string>.Info = "A string associated with string";

and is accessed like,

Console.WriteLine(Data<int, string>.Info);
Console.WriteLine(Data<string, string>.Info);

This works because static variables of a generic class are unique for distinct generic parameters.

If the type is not statically available then you should use Dictionary<Type, V> as mentioned in your question and recommended by others.

chuckj
Very interesting to point out a way of doing it statically, but it was not the case. Dictionaries keyed by Type are actually the best way to do it... I was wrong, it is not an order of magnitude slower than virtual calls, it is just 3-4 times slower... that is enough for me. Thanks!
Miguel Angelo
I like this method, actually. It's pretty sneaky though, almost a hack... makes use of a slightly subtle CLR feature to accomplish the task quite nicely.
Noldorin
A: 

As other people have said, you are probably micro-optimizing, but since we are all getting into the spirit of it, I will too :)

The .NET type class can be boiled down to it's runtime type handle which can be more efficient than the full type if you don't need reflection...

Dictionary or whatever you are using is about 20% faster than Dictionary in the very simple test I just ran.

typeof(object).RuntimeTypeHandle;
// and
instance.GetType().RuntimeTypeHandle;

can be used in place of a full type instance

StarBright