C# 创建基于编译器的非静态版本";字典;其中键是类型

C# 创建基于编译器的非静态版本";字典;其中键是类型,c#,.net,generics,dictionary,compile-time,C#,.net,Generics,Dictionary,Compile Time,有一个非常简单的技巧可以创建一个类似字典的结构,其中键是类型。 该结构就像一个字典,其中键是类型对象,值是相应类型的实例 这种奇妙的结构就像一个变量或数组一样快,因为编译器/抖动只执行一次“查找”,并且正确的值引用被编译到程序中 public static class MyDict<T> { public static T Value { get; set; } } 公共静态类MyDict{ 公共静态T值{get;set;} } 您可以像这样使用该

有一个非常简单的技巧可以创建一个类似字典的结构,其中键是类型。 该结构就像一个
字典
,其中键是
类型
对象,值是相应类型的实例

这种奇妙的结构就像一个变量或数组一样快,因为编译器/抖动只执行一次“查找”,并且正确的值引用被编译到程序中

    public static class MyDict<T> {
        public static T Value { get; set; }
    }
公共静态类MyDict{
公共静态T值{get;set;}
}
您可以像这样使用该结构:

MyDict<string>.Value = MyDict<int>.Value.ToString();
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();
void X()
{
    var a = new TypeDict();
    var b = new TypeDict();

    a.Set<int>(1);
    a.Set<double>(3.14);
    a.Set("Hello, world!");

    //Note that type inference allows us to omit the type argument
    b.Set(10);          
    b.Set(31.4);  
    b.Set("Hello, world, times ten!");

    Console.WriteLine(a.Get<int>());
    Console.WriteLine(a.Get<double>());
    Console.WriteLine(a.Get<string>());

    Console.WriteLine();
    Console.WriteLine(b.Get<int>());
    Console.WriteLine(b.Get<double>());
    Console.WriteLine(b.Get<string>());
}
MyDict.Value=MyDict.Value.ToString();
问题是这本“词典”是全球性的。创建不同词典的唯一方法是创建不同的类

如何创建类似的(最快的“查找”,无装箱)非静态结构?(不生成代码。)


简单地说:我希望有多个类似于
字典的对象,而不需要查找成本、强制转换和装箱。

Ark kun正在使用泛型在编译时生成唯一的类型。对于泛型类型,任何静态成员都是该特定封闭泛型类型的唯一成员。这样,它的处理速度与标准静态成员查找一样快

上述用法相当于这样的用法:

MyDict<string>.Value = MyDict<int>.Value.ToString();
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();
void X()
{
    var a = new TypeDict();
    var b = new TypeDict();

    a.Set<int>(1);
    a.Set<double>(3.14);
    a.Set("Hello, world!");

    //Note that type inference allows us to omit the type argument
    b.Set(10);          
    b.Set(31.4);  
    b.Set("Hello, world, times ten!");

    Console.WriteLine(a.Get<int>());
    Console.WriteLine(a.Get<double>());
    Console.WriteLine(a.Get<string>());

    Console.WriteLine();
    Console.WriteLine(b.Get<int>());
    Console.WriteLine(b.Get<double>());
    Console.WriteLine(b.Get<string>());
}
顺便说一句,类型是“静态的”(在这种情况下不能定义多个类型),所以我不知道有什么方法可以绕过它并保持静态编译成员查找的相同性能

否则(我认为)最好的办法是创建一个通用实例类型,它包装自己的字典,使用
System.type
作为其键,使用
System.Object
作为其值,在插入/检索值时必须对其执行装箱/强制转换

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

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;
    }
}
public class MyDictionary<T>
{
    Dictionary<string, T> dict;

    public MyDictionary()
    {
        dict = new Dictionary<string, T>();
    }

    public T this[string name]
    {
        get
        {
            if (dict.ContainsKey(name))
                return dict[name];
            else
                return default(T);//or throw
        }
        set
        {
            dict[name] = value;
        }
    }
}
其用法如下:

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!
无论如何,我认为这很奇怪,我不推荐它。

试试这个:

public class MyDictionary
{
    List<object> values;

    public MyDictionary()
    {
        values = new List<object>();
    }

    public T GetValue<T>()
    {
        return values.OfType<T>().FirstOrDefault();
    }

    public bool Add<T>(T value)
    {
        if (values.OfType<T>().Any())
            return false;
        else
        {
            values.Add(value);
            return true;
        }
    }
}
公共类MyDictionary
{
列表值;
公共MyDictionary()
{
值=新列表();
}
公共T GetValue()
{
返回值.OfType().FirstOrDefault();
}
公共布尔加法(T值)
{
if(value.OfType().Any())
返回false;
其他的
{
增加(价值);
返回true;
}
}
}
并使用它:

var md = new MyDictionary();
md.Add("!!!");
string s = md.GetValue<string>();
var md=new MyDictionary();
md.Add(“!!!”);
字符串s=md.GetValue();

此类最多可存储一个
T
类型的值。但我想可能会有派生类和接口的情况。您可以检查它是否适合您的需要,如果它接近您通常需要的内容,您可以根据需要修改它。

更复杂的版本。不知道它是否更近:

定义通用词典:

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;
    }
}
public class MyDictionary<T>
{
    Dictionary<string, T> dict;

    public MyDictionary()
    {
        dict = new Dictionary<string, T>();
    }

    public T this[string name]
    {
        get
        {
            if (dict.ContainsKey(name))
                return dict[name];
            else
                return default(T);//or throw
        }
        set
        {
            dict[name] = value;
        }
    }
}
然而,这与与与其他人一起工作是一样的

Dictionary<string, int> intDict = new Dictionary<string, int>();
Dictionary intDict=new Dictionary();

因此,
MyRepository
类可能会被编辑为使用
Dictionary
而不是
MyDictionary

@Konstantin的回答让我记住,实际上有一种非常快速的查找方法-数组索引。此原始PoC代码显示了所需结构的变体

    public class TypeDictionary {
        static int _maxId = 0;
        int _id;

        static class Store<T>{
            internal static List<T> Values = new List<T>();
        }

        public TypeDictionary() {
            _id = _maxId++;
        }

        public T GetValue<T>() {
            return Store<T>.Values[_id];
        }

        public void SetValue<T>(T value) {
            while(Store<T>.Values.Count < _id) {
                Store<T>.Values.Add(default(T));
            }
            Store<T>.Values[_id] = value;
        } 
    }
公共类类型字典{
静态int_maxId=0;
内部id;
静态类存储{
内部静态列表值=新列表();
}
公共类型词典(){
_id=_maxId++;
}
公共T GetValue(){
返回Store.Values[_id];
}
公共无效设置值(T值){
while(Store.Values.Count<\u id){
Store.Values.Add(默认值(T));
}
Store.Values[_id]=值;
} 
}
此代码可按如下方式使用:

        var dict1 = new TypeDictionary();
        dict1.SetValue("my string");
        string result = dict1.GetValue<string>();
var dict1=新类型字典();
dict1.SetValue(“我的字符串”);
字符串结果=dict1.GetValue();

此解决方案的问题在于,存储库不是稀疏的,这会导致内存占用。这也使得首次设置值的成本更高。

以下是一种扩展问题中所述方法的方法:

public class TypeDict
{
    public T Get<T>()
    {
        return MyDict<T>.Values[this];
    }
    public void Set<T>(T value)
    {
        MyDict<T>.Values[this] = value;
    }
    private static class MyDict<T>
    {
        public static Dictionary<TypeDict, T> Values { get; private set; }

        static MyDict()
        {
            Values = new Dictionary<TypeDict, T>();
        }
    }
}
公共类TypeDict
{
公共部门得不到
{
返回MyDict.值[此];
}
公共无效集(T值)
{
MyDict.Values[此]=值;
}
私有静态类MyDict
{
公共静态字典值{get;private set;}
静态MyDict()
{
值=新字典();
}
}
}
现在我们可以像这样使用TypeDict:

MyDict<string>.Value = MyDict<int>.Value.ToString();
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();
void X()
{
    var a = new TypeDict();
    var b = new TypeDict();

    a.Set<int>(1);
    a.Set<double>(3.14);
    a.Set("Hello, world!");

    //Note that type inference allows us to omit the type argument
    b.Set(10);          
    b.Set(31.4);  
    b.Set("Hello, world, times ten!");

    Console.WriteLine(a.Get<int>());
    Console.WriteLine(a.Get<double>());
    Console.WriteLine(a.Get<string>());

    Console.WriteLine();
    Console.WriteLine(b.Get<int>());
    Console.WriteLine(b.Get<double>());
    Console.WriteLine(b.Get<string>());
}
void X()
{
var a=新类型dict();
var b=新类型dict();
a、 一套(1);
a、 组(3.14);
a、 布景(“你好,世界!”);
//注意,类型推断允许我们省略类型参数
b、 组(10);
b、 组(31.4);
b、 集合(“你好,世界,十倍!”);
Console.WriteLine(a.Get());
Console.WriteLine(a.Get());
Console.WriteLine(a.Get());
Console.WriteLine();
Console.WriteLine(b.Get());
Console.WriteLine(b.Get());
Console.WriteLine(b.Get());
}

在C#中,您所寻找的是不可能的。该语言不支持可以存储多个不同类型对象的容器,但提供了一种不涉及强制转换、装箱或取消装箱的查找方法。您可以用C++中的宏或通过JavaScript之类的语言来完成这类事情,在运行时可以改变类型的结构。

< P>您所描述的用例与“.Cudith> AtdialAuthTabue/Cuth>”的目的非常接近。出于您描述的目的,您将在静态泛型类中包含这样一个表,然后对于每个假定包含对特定类型项的引用的类对象,您将在该类型的表中存储对假定的对象的引用