创建一个非静态版本的编译型&QUOT的;字典"其中,键类型创建一个、静态、字典、版本

2023-09-05 04:11:51 作者:屏蔽一段往昔

有一个非常简单的技巧创造一个类似于字典的结构,其中键的类型。 结构就像一个词典<类型,T> ,其中键键入对象和值的情况下,相应的类型。

There is a very easy trick which creates a dictionary-like structure where keys are types. The structure acts like a Dictionary<Type, T?> where keys are Type objects and values are instances of the corresponding types.

这美妙的结构是因为查找仅是由编译器/抖动和正确的价值基准做一次被编译到你的程序一样快,只是一个变量或数组。

This wonderful structure is as fast as just a variable or array since the "lookup" is only done once by the compiler/JITter and the proper value reference is compiled into your program.

    public static class MyDict<T> {
        public static T Value { get; set; }
    }

您可以与结构像这样的工作:

You can work with that structure like this:

MyDict<string>.Value = MyDict<int>.Value.ToString();

的问题是,这种字典是全球性的。创建不同的字典,唯一的方法是创建不同的类。

The problem is that this "dictionary" is global. The only way to create different dictionaries is to create different classes.

如何创建一个类似的(速度最快的查找,没有拳击)非静态的结构呢? (如果没有code一代。)

How can create a similar (fastest "lookup", no boxing) non-static structure? (Without code generation.)

简单地说:我想有多个词典&LT;类型,对象&gt; 样的对象,而不查找成本,铸造和拳击

Simply said: I want to have multiple Dictionary<Type, object>-like objects without lookup costs, casting and boxing.

推荐答案

方舟坤被使用泛型基本上产生独特类型在编译时。随着泛型类型,任何静态成员是唯一的特定封闭泛型类型。这样,它的处理速度是一个标准的静态成员查找。

Ark-kun is using generics to essentially generate unique types at compile time. With a generic type, any static members are unique to that specific closed generic type. This way it's processed as fast as a standard static member lookup.

以上使用相当于是这样的:

The above usage is equivalent to something like this:

public static class MyDict_String 
{
    public static string Value { get; set; }
}

public static class MyDict_Int32
{
    public static int Value { get; set; }
}

MyDict_String.Value = MyDict_Int32.Value.ToString();

AFAIK,类型为静态(中,你不能定义多个这样),所以我不知道的方式来欺骗周围,并保持一个静态编译成员查找相同的性能。

AFAIK, types are "static" (in that you can't define more than one that way) so I don't know of a way to cheat around this and maintain the same performance of a statically compiled member lookup.

您最好的选择,否则,(我认为)是创建一个包装了自己的字典,使用的System.Type 其键和 System.Object的为它的值,你必须插入/检索值时,进行装箱/铸造。

Your best bet otherwise (I think) is to create a generic instance type that wraps its own dictionary that uses System.Type for its keys and System.Object for its values to which you have to perform boxing/casting when inserting/retrieving values.

编辑:下面是一个简单的实现封装字典:

Here's a simple implementation wrapping a dictionary:

public class MyTypedDict
{
    private Dictionary<Type, object> Values = new Dictionary<Type, object>();

    public T Get<T>()
    {
        object untypedValue;
        if (Values.TryGetValue(typeof(T), out untypedValue))
            return (T)untypedValue;
        return default(T);
    }

    public void Set<T>(T value)
    {
        Values[typeof(T)] = value;
    }
}

这件事想的更多,有可能使用实现多个属性的语法的 ExpandoObject ( http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx )通过一些蠢事,但我觉得这将是pretty的辱骂,我只能假设非常容易出现运行错误。 (再加上它会提供你没有在编译时)

Thinking about it more, it might be possible to achieve a more property-like syntax using an ExpandoObject (http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx) through some tomfoolery, but I feel like this would be pretty abusive and I can only assume terribly prone to runtime errors. (plus it would afford you nothing at compile time)

EDITx2:如果你真的想拥有的不同的值的,你的可以的在另一个泛型类型嵌套的:

EDITx2: If you really want to have different sets of values, you could nest it within another generic type:

public static class ValueSets<T>
{
    public static class MyDict<U>
    {
        public static U Value { get; set; }
    }
}

通过使用这样的:

ValueSets<int>.MyDict<string>.Value = "Hello ";
ValueSets<bool>.MyDict<string>.Value = "World!";

string helloworld = ValueSets<int>.MyDict<string>.Value + ValueSets<bool>.MyDict<string>.Value;
Console.WriteLine(helloworld);//Hello World!

但随后的初始类型 INT 布尔在这种情况下,成为神奇,没有意义,再加上你需要提供每个不同的价值观,你想使用一个独特的类型。另外,您不能错过它周围和修改作为一个实例变量,而这将会是静态访问(只要你有机会获得使用类型 T )。因此,也许你可以声明微创可视类型的命名意义和使用这些:

But then the initial type int and bool in this case become "magical" and without meaning, plus you would need to provide a unique type per distinct set of values you'd like to use. Plus you could not pass it around and modify as an instance variable, rather it'd be statically accessible (so long as you have access to use the type T). So perhaps you could declare minimally visible types that are named with meaning and use those:

internal class MyFirstWords {}
internal class MySecondWords {}

ValueSets<MyFirstWords>.MyDict<string>.Value = "Hello ";
ValueSets<MySecondWords>.MyDict<string>.Value = "World!";

string helloworld = ValueSets<MyFirstWords>.MyDict<string>.Value + ValueSets<MySecondWords>.MyDict<string>.Value;
Console.WriteLine(helloworld);//Hello World!

无论如何,我认为这是相当古怪的,我不会推荐它。

Regardless, I think this is quite wacky and I wouldn't recommend it.