如果存在多个具有相同值的枚举常量,是否存在一个常数我得到的逻辑?
我尝试了下面的变化,但无法得到合理的逻辑.
public class Program
{
public static void Main(string[] args)
{
Test a = 0;
Console.WriteLine(a);
}
}
Run Code Online (Sandbox Code Playgroud)
enum Test
{
a1=0,
a2=0,
a3=0,
a4=0,
}
Run Code Online (Sandbox Code Playgroud)
输出:
a2
Run Code Online (Sandbox Code Playgroud)
enum Test
{
a1=0,
a2=0,
a3,
a4=0,
}
Run Code Online (Sandbox Code Playgroud)
输出:
a4
Run Code Online (Sandbox Code Playgroud)
enum Test
{
a1=0,
a2=0,
a3,
a4,
}
Run Code Online (Sandbox Code Playgroud)
输出:
a2
Run Code Online (Sandbox Code Playgroud)
enum Test
{
a1=0,
a2=0,
a3,
a4
}
Run Code Online (Sandbox Code Playgroud)
输出:
a1
Run Code Online (Sandbox Code Playgroud)
D S*_*ley 68
该文件实际上解决了这个:
如果多个枚举成员具有相同的基础值,并且您尝试根据其基础值检索枚举成员名称的字符串表示形式,则您的代码不应对该方法将返回的名称做出任何假设.
(重点补充)
但是,这并不意味着结果是随机的.这意味着它是一个可能会发生变化的实现细节.只需一个补丁就可以完全改变实现,在编译器(MONO,Roslyn等)之间可能会有所不同,并且在不同的平台上会有所不同.
如果您的系统设计为要求枚举的反向查找在时间和平台上保持一致,则不要使用 Enum.ToString
.要么改变你的设计,所以它不是依赖于细节,或写你自己的方法将是一致的.
因此,您不应编写依赖于该实现的代码,否则您将承担在未来版本中不知情的情况下会发生变化的风险.
Xia*_*312 28
TL; DR:枚举的所有字段将通过反射提取,然后插入排序并二进制搜索第一个匹配值.
调用链看起来像这样:
Enum.Tostring();
Enum.InternalFormat(RuntimeType eT, Object value);
Enum.GetName(Type enumType, Object value);
Type.GetEnumName(object value);
Run Code Online (Sandbox Code Playgroud)
Type.GetEnumName(object value)
实施如下:
public virtual string GetEnumName(object value)
{
// standard argument guards...
Array values = GetEnumRawConstantValues();
int index = BinarySearch(values, value);
if (index >= 0)
{
string[] names = GetEnumNames();
return names[index];
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
双方GetEnumRawConstantValues()
并GetEnumNames()
依靠GetEnumData(out string[] enumNames, out Array enumValues)
:
private void GetEnumData(out string[] enumNames, out Array enumValues)
{
Contract.Ensures(Contract.ValueAtReturn<String[]>(out enumNames) != null);
Contract.Ensures(Contract.ValueAtReturn<Array>(out enumValues) != null);
FieldInfo[] flds = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
object[] values = new object[flds.Length];
string[] names = new string[flds.Length];
for (int i = 0; i < flds.Length; i++)
{
names[i] = flds[i].Name;
values[i] = flds[i].GetRawConstantValue();
}
// Insertion Sort these values in ascending order.
// We use this O(n^2) algorithm, but it turns out that most of the time the elements are already in sorted order and
// the common case performance will be faster than quick sorting this.
IComparer comparer = Comparer.Default;
for (int i = 1; i < values.Length; i++)
{
int j = i;
string tempStr = names[i];
object val = values[i];
bool exchanged = false;
// Since the elements are sorted we only need to do one comparision, we keep the check for j inside the loop.
while (comparer.Compare(values[j - 1], val) > 0)
{
names[j] = names[j - 1];
values[j] = values[j - 1];
j--;
exchanged = true;
if (j == 0)
break;
}
if (exchanged)
{
names[j] = tempStr;
values[j] = val;
}
}
enumNames = names;
enumValues = values;
}
Run Code Online (Sandbox Code Playgroud)
如果遵循,GetFields(BindingFlags bindingAttr)
导致一个abstract
方法,但在msdn上搜索"GetFields"将产生你EnumBuilder.GetFields(BindingFlags bindingAttr)
.如果我们遵循其呼叫链:
EnumBuilder.GetFields(BindingFlags bindingAttr);
TypeBuilder.GetFields(BindingFlags bindingAttr);
RuntimeType.GetFields(BindingFlags bindingAttr);
RuntimeType.GetFieldCandidates(String name, BindingFlags bindingAttr, bool allowPrefixLookup);
RuntimeTypeCache.GetFieldList(MemberListType listType, string name);
RuntimeTypeCache.GetMemberList<RuntimeFieldInfo>(ref MemberInfoCache<T> m_cache, MemberListType listType, string name, CacheType cacheType);
MemberInfoCache<RuntimeFieldInfo>.GetMemberList(MemberListType listType, string name, CacheType cacheType);
MemberInfoCache<RuntimeFieldInfo>.Populate(string name, MemberListType listType, CacheType cacheType);
MemberInfoCache<RuntimeFieldInfo>.GetListByName(char* pName, int cNameLen, byte* pUtf8Name, int cUtf8Name, MemberListType listType, CacheType cacheType);
MemberInfoCache<RuntimeFieldInfo>.PopulateFields(Filter filter);
// and from here, it is a wild ride...
Run Code Online (Sandbox Code Playgroud)
所以,我会引用一些Type.GetFields
评论:
GetFields方法不按特定顺序返回字段,例如按字母顺序或声明顺序.您的代码不得依赖于返回字段的顺序,因为该顺序会有所不同.
归档时间: |
|
查看次数: |
2458 次 |
最近记录: |