c# - 没有类型参数的 C# Generic DynamicMethod
问题描述
出于性能原因,我正在尝试编写一个 IL 委托,它可以KeyValuePair
从字典中返回随机数,而无需使用枚举。为此,我直接从字典_bucket
和_entries
字段中读取。
Dictionary
是一个通用集合,但我想避免为每个单独的类型编译一个委托,而只返回一个装箱的对象。但是,以这种方式使用泛型似乎有点麻烦。
这是我目前所在的位置。请注意,实现不完整:
public static class DictionaryExtensions
{
private delegate object RandomDelegate( IDictionary dict, Random random );
private static RandomDelegate randomDel;
static DictionaryExtensions()
{
randomDel = CompileRandomDel();
}
public static object RandomValue<TKey, TValue>( this Dictionary<TKey, TValue> dict, Random rand )
{
var x = randomDel( dict, rand );
return x;
}
private static RandomDelegate CompileRandomDel()
{
var bucketsField = typeof( Dictionary<,> ).GetField( "_buckets", BindingFlags.Instance | BindingFlags.NonPublic );
var entriesField = typeof( Dictionary<,> ).GetField( "_entries", BindingFlags.Instance | BindingFlags.NonPublic );
var randNext = typeof( Random ).GetMethod( "Next", Type.EmptyTypes );
var method = new DynamicMethod(
"RandomEntry",
MethodAttributes.Public | MethodAttributes.Static,
CallingConventions.Standard,
typeof( object ),
new[] { typeof( Dictionary<,> ), typeof( Random ) },
typeof( DictionaryExtensions ),
false );
var il = method.GetILGenerator();
il.DeclareLocal( typeof( int ) ); // Loc_0: Bucket
il.Emit( OpCodes.Ldarg_1 ); // Load random
il.Emit( OpCodes.Call, randNext ); // Get next random int
//il.Emit( OpCodes.Ldarg_0 ); // Load dictionary
//il.Emit( OpCodes.Ldfld, bucketsField ); // Load buckets
//il.Emit( OpCodes.Ldlen ); // Load buckets length
//il.Emit( OpCodes.Rem ); // random % bucket count
//il.Emit( OpCodes.Ldelem ); // Load bucket
//il.Emit( OpCodes.Stloc_0 ); // Store bucket in loc_0
//il.Emit( OpCodes.Ldarg_0 ); // Load dictionary
//il.Emit( OpCodes.Ldfld, entriesField ); // Load dictionary entries
//il.Emit( OpCodes.Ldloc_0 ); // Load bucket
//il.Emit( OpCodes.Ldelem ); // Load element at bucket
// Debug (just returning the random int for now)
il.Emit( OpCodes.Conv_I4 );
il.Emit( OpCodes.Box, typeof( int ) );
il.Emit( OpCodes.Ret );
return ( RandomDelegate ) method.CreateDelegate( typeof( RandomDelegate ) );
}
}
我的问题似乎是缺乏特定的通用论点。运行该方法会导致TypeInitialization: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B).
如果我将 DynamicMethod 的参数从 更改Dictionary<,>
为IDictionary
,则可以。但是,这是危险的,因为并非所有IDictionary
实现都是平等的,并且此委托仅用于实际Dictionary<,>
类型。除此之外,似乎使用IDictionary
可能会搞砸字段的加载,因为InvalidProgramException
当我尝试仅加载_entries
字段的长度并返回它时,它会抛出一个。
因此,在不指定参数的情况下使用泛型类型是不行的。有没有其他方法可以编译一个适用于所有泛型类型参数的安全委托?由于返回值只是一个装箱的值,object
我认为不需要为遇到的每种类型编译一个委托,但如果这是不可避免的,我想我别无选择。
解决方案
推荐阅读
- python - Python Pandas 查询缺少数据的多个文件
- python - Python OOP - 使用实例变量
- reactjs - 从表单输入更改状态对象变量 - ReactJS
- python - - 不支持的操作数类型:'float' 和 'tuple' - 有趣的错误
- c# - 我没有在 swagger.json 中获得方法描述
- javascript - 在 IME 合成期间将光标移动到其他文本框
- android-studio - Android Studio Sidebars Gone and Not Pinning Correctly
- python - How to iterate through the zeroth index for every item in list in Python
- elasticsearch - How to add namespace to ELK cluster vi elasticsearch.yml in kubernetes
- html - Using custom font on webpage issue