我事先表示歉意。我的领域主要是C(和C ++)。我正在尝试用C#编写类似的内容。让我用代码解释。
在C ++中,我可以使用大型静态数组,这些静态数组在编译时进行处理并存储在PE文件的只读部分中。例如:
typedef struct _MY_ASSOC{
const char* name;
unsigned int value;
}MY_ASSOC, *LPMY_ASSOC;
bool GetValueForName(const char* pName, unsigned int* pnOutValue = nullptr)
{
bool bResult = false;
unsigned int nValue = 0;
static const MY_ASSOC all_assoc[] = {
{"name1", 123},
{"name2", 213},
{"name3", 1433},
//... more to follow
{"nameN", 12837},
};
for(size_t i = 0; i < _countof(all_assoc); i++)
{
if(strcmp(all_assoc[i].name, pName) == 0)
{
nValue = all_assoc[i].value;
bResult = true;
break;
}
}
if(pnOutValue)
*pnOutValue = nValue;
return bResult;
}
在上面的示例中,static const MY_ASSOC all_assoc
的初始化在运行时从未调用。它是在编译时完全处理的。
现在,如果我用C#编写类似的内容:
public struct NameValue
{
public string name;
public uint value;
}
private static readonly NameValue[] g_arrNV_Assoc = new NameValue[] {
new NameValue() { name = "name1", value = 123 },
new NameValue() { name = "name2", value = 213 },
new NameValue() { name = "name3", value = 1433 },
// ... more to follow
new NameValue() { name = "nameN", value = 12837 },
};
public static bool GetValueForName(string name, out uint nOutValue)
{
foreach (NameValue nv in g_arrNV_Assoc)
{
if (name == nv.name)
{
nOutValue = nv.value;
return true;
}
}
nOutValue = 0;
return false;
}
private static readonly NameValue[] g_arrNV_Assoc
行在主机类初始化期间必须被调用一次,并且必须为该数组中的每个元素完成一次!
我的问题-我可以以某种方式对其进行优化,以便将存储在g_arrNV_Assoc
数组中的数据存储在PE部分中,而不在运行时初始化吗?
PS。我希望我对自己的术语了解.NET。
答案 0 :(得分:1)
实际上,术语足够,大型静态数组就可以了。
您没有真正能做的事情来使它更有效。
它最初将加载一次(在不同时间加载,具体取决于.net的版本以及是否具有静态构造函数)。但是,它将在调用之前加载。
即使您以预定的大小将其创建为空,CLR仍将每个元素初始化为默认值,然后您仍必须以某种方式缓冲数据上的副本,这又将不得不从文件中加载。
问题是
如果这是太多的开销(我已经假设您已经确定),那么框外还有哪些其他选项可用?
您可以预先分配一块非托管内存,然后从某个位置读取和复制字节,然后使用指针进行访问。
您还可以像其他不受管理的DLL一样,在标准的Dll Pinvoke中创建此文件。但是我真的不太确定您是否会在这里得到很多免费午餐,因为要整理这些调用来加载您的dll会有开销。
如果您的问题只是学术性的,那么实际上这是您唯一的选择。但是,如果这实际上是您遇到的性能问题,则需要尝试对其进行基准测试以进行微优化,然后尝试找出适合您的条件。
无论如何,我不承认所有知识,也许其他人有更好的主意或更多信息。祝你好运