enum 值上调用 ToString() 时,什么决定选择哪个名称?问题的详细解释如下。
我已经确定这不是由以下任何一个唯一确定的:字母顺序;申报单;也不,名称长度。
例如,假设我想要一个枚举,其中数值直接对应于实际用途(例如颜色的 rgb 值)。
public enum RgbColor
{
Black = 0x000000,
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
White = 0xffffff
}
现在,使用此枚举,调用 default(RgbColor) 将返回黑色的 rgb 值。假设我不希望默认值为黑色,因为我希望 UI 设计人员在没有关于使用什么颜色的具体说明时能够使用对“默认”的调用。目前,UI 设计师使用的默认值实际上是“蓝色”,但这可能会改变。因此,我在枚举上添加了一个额外的 TextDefault 定义,现在它看起来像:
public enum RgbColorWithTextDefaultFirst
{
TextDefault = 0x0000ff,
Black = 0x000000,
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
White = 0xffffff
}
现在,我已经对此进行了测试,我发现调用 RgbColorWithTextDefaultFirst.TextDefault.ToString() 和 RgbColorWithTextDefaultFirst.Blue.ToString() 都会产生“蓝色”。所以,我认为最后声明的名称将覆盖之前声明的名称。为了验证我的假设,我写道:
public enum RgbColorWithTextDefaultLast
{
Black = 0x000000,
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
White = 0xffffff,
TextDefault = 0x0000ff
}
然而,令我惊讶的是,RgbColorWithTextDefaultLast.Blue.ToString() 和 RgbColorWithTextDefaultLast.TextDefault.ToString()。我的下一个猜测是它按字母顺序对名称进行排序并返回第一个。为了测试这一点,我尝试:
public enum RgbColorWithATextDefaultFirst
{
ATextDefault = 0x0000ff,
Black = 0x000000,
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
White = 0xffffff
}
public enum RgbColorWithATextDefaultLast
{
Black = 0x000000,
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
White = 0xffffff,
ATextDefault = 0x0000ff
}
现在,对于所有四个 RgbColorWithATextDefaultFirst.ATextDefault.ToString(),RgbColorWithATextDefaultFirst.Blue.ToString(),RgbColorWithATextDefaultLast.ATextDefault.ToString(),RgbColorWithATextDefaultLast.Blue.ToString(),我以“Blue”结尾。我意识到还有另一个区别因素,即字符串的长度。我现在的猜测是,所选名称由名称字符串的长度决定。所以,我的测试是使用这些声明:
public enum RgbColorWithALast
{
Black = 0x000000,
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
White = 0xffffff,
A = 0x0000ff
}
public enum RgbColorWithAFirst
{
A = 0x0000ff,
Black = 0x000000,
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
White = 0xffffff
}
现在,猜猜我得到的所有值是什么:RgbColorWithAFirst.A.ToString(); RgbColorWithAFirst.Blue.ToString(); RgbColorWithALast.A.ToString(),RgbColorWithALast.Blue.ToString()。没错,就是“蓝”。
在这一点上,我已经放弃了试图通过猜测来弄清楚是什么决定了这一点。我打开了 Reflector,我打算看看并尝试弄清楚这个问题,但我想我会在这里问一个问题,看看这里是否有人已经知道答案,也就是:什么决定了在具有多个对应名称的 enum 值上调用 ToString() 时选择哪个名称?
最佳答案
我在这里可能走得太远了,但我认为它是由排序值的二进制搜索决定的,因此可能取决于值总数的奇偶校验。您可以通过在两者中定义另一个值来用最后一个示例(RgbColorWithAFirst 和 RgbColorWithALast)来说明这一点 - 然后您从所有 中获得 调用。A >ToString
我通过反编译 mscorlib (4.0) 到达这里,并注意到最终我们在声明值的排序数组上调用了 Array.BinarySearch。自然地,二分搜索一旦找到匹配项就会停止,因此要让它在两个相同的值之间切换,最简单的方法是通过添加一个额外的值来更改搜索树。
当然,这是一个实现细节,不应依赖。在我看来,在您的情况下,最好通过在您希望明确显示值的枚举值上使用 DescriptionAttribute 以及辅助方法,例如:
public static class EnumExtensions
{
public static string Description(this Enum value)
{
var field = value.GetType().GetField(value.ToString());
var attribute = Attribute.GetCustomAttribute(
field,
typeof (DescriptionAttribute))
as DescriptionAttribute;
return attribute == null ? value.ToString() : attribute.Description;
}
}
关于c# - 在具有多个对应名称的枚举值上调用 ToString() 时,什么决定选择哪个名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12711059/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput