【发布时间】:2012-02-10 22:28:23
【问题描述】:
短版
Type.GetProperties 的 MSDN 文档指出,它返回的集合不能保证按字母顺序或声明顺序,尽管运行一个简单的测试表明它通常按声明顺序返回。您是否知道某些特定情况并非如此?除此之外,建议的替代方案是什么?
详细版本
我意识到 Type.GetProperties 状态的 MSDN 文档:
GetProperties 方法不返回特定的属性 顺序,例如字母顺序或声明顺序。您的代码不得 取决于返回属性的顺序,因为 顺序不同。
因此无法保证该方法返回的集合将以任何特定方式排序。根据一些测试,我发现返回的属性按照它们在类型中定义的顺序出现。
例子:
class Simple
{
public int FieldB { get; set; }
public string FieldA { get; set; }
public byte FieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Simple Properties:");
foreach (var propInfo in typeof(Simple).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
输出:
Simple Properties:
FieldB
FieldA
FieldC
这种情况略有不同的一种情况是,当所讨论的类型的父级也具有属性时:
class Parent
{
public int ParentFieldB { get; set; }
public string ParentFieldA { get; set; }
public byte ParentFieldC { get; set; }
}
class Child : Parent
{
public int ChildFieldB { get; set; }
public string ChildFieldA { get; set; }
public byte ChildFieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Parent Properties:");
foreach (var propInfo in typeof(Parent).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
Console.WriteLine("Child Properties:");
foreach (var propInfo in typeof(Child).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
输出:
Parent Properties:
ParentFieldB
ParentFieldA
ParentFieldC
Child Properties:
ChildFieldB
ChildFieldA
ChildFieldC
ParentFieldB
ParentFieldA
ParentFieldC
这意味着GetProperties 方法在发现属性时会自下而上地沿着继承链向上走。没关系,可以这样处理。
问题:
- 是否存在我错过的描述行为会有所不同的特定情况?
- 如果不推荐根据顺序,那么推荐的方法是什么?
一个看似显而易见的解决方案是定义一个自定义属性,该属性指示属性应该出现的顺序(类似于DataMember 属性上的Order 属性)。比如:
public class PropOrderAttribute : Attribute
{
public int SeqNbr { get; set; }
}
然后实现如:
class Simple
{
[PropOrder(SeqNbr = 0)]
public int FieldB { get; set; }
[PropOrder(SeqNbr = 1)]
public string FieldA { get; set; }
[PropOrder(SeqNbr = 2)]
public byte FieldC { get; set; }
}
但正如许多人所发现的,如果您的类型有 100 个属性并且您需要在前 2 个属性之间添加一个,这将成为一个严重的维护问题。
更新
此处显示的示例仅用于演示目的。在我的特定场景中,我使用类定义消息格式,然后遍历类的属性并获取它们的属性以查看应如何解组消息中的特定字段。消息中字段的顺序很重要,因此我的类中的属性顺序也很重要。
它目前仅通过迭代来自 GetProperties 的返回集合来工作,但由于文档指出不建议这样做,我希望了解为什么以及我还有什么其他选择?
【问题讨论】:
-
你想达到什么目的?为什么需要订单?或许还有其他方法
-
基本上,文档说“不要依赖订单”,但在当前的实现中,它可能会有一个一致的订单。文档是准确的,“不要依赖订单”并不意味着“它会有所不同”。这意味着“它可能会有所不同”。 Q1:你不能假设它会像你再次描述的那样。 Q2:不要依赖订单。如果您需要有序列表,请自行订购。
-
1.您完全不应该依赖声明顺序 - 这是肯定的,因为它取决于运行时的实现(它甚至可以从一个版本更改为另一个版本)。
-
2. 为什么不按字母顺序对属性进行排序?还是您需要其他排序顺序?
-
@KierenJohnstone - 我已经根据问题的上下文更新了问题。我有什么选择?
标签: c# reflection