在查看Winforms中生成的代码时,我注意到一些看似毫无意义的内容:
this.aButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))),
((int)(((byte)(101)))),
((int)(((byte)(162)))));
Color.FromArgb可以使用int,那么为什么需要那些(int)和(byte)转换?为什么VS不会生成
this.aButton.BackColor = System.Drawing.Color.FromArgb(0, 101, 162)?
答案 0 :(得分:2)
嗯,它看起来像一些“万无一失”的机制。由于每个颜色分量值应小于256(颜色限制为8位),因此如果开发人员以某种方式输入大于255的值作为颜色分量,则将此值转换为byte
将阻止编译程序。
即。这样:(byte)256
将生成编译器错误,从而向开发人员显示颜色组件值的问题。
答案 1 :(得分:0)
这是设计师如何序列化属性值的人工制品。该属性使用TypeConverter
序列化为InstanceDescriptor
。
实例描述符包含从颜色对象的R,G和B属性存储为字节的参数,如下所示:
var color = System.Drawing.Color.FromArgb(255, 128, 64);
var converter = TypeDescriptor.GetConverter(color);
var result = (InstanceDescriptor) converter.ConvertTo(color, typeof(InstanceDescriptor));
var arguments = result.Arguments.Cast<object>().ToList();
Console.WriteLine(arguments[0] is byte);
之后,实例描述符转换为CodeDom,然后保存为C#代码。
CodeDom只是准确地再现了它的内容,因为C#没有本地字节类型,它将一个强制转换输出到一个字节。然后CodeDom看到它调用一个需要int
的方法,但它有一个byte
,所以将这些值转换为int
,这是因为存在一个字节的重载或稍后加入。
CodeDom以这种方式表现,因为它不会造成任何伤害并且很容易。负责序列化常量值的部分不需要知道或关心如何使用该值。负责生成方法调用的部分不需要知道或关心值的来源(在这种情况下是一个常量,但它可能是变量,属性,方法调用等)。冗余将是由编译器拾取并优化掉。
ColorConverter可以通过在为实例描述符生成参数时首先将字节转换为int来避免这种情况,但同样,额外工作和复杂性的重点是什么。