Короткая версия
В документации MSDN для Type.GetProperties
указано, что возвращаемая коллекция не гарантируется в алфавитном порядке или в порядке декларирования, хотя и выполняетсяпростой тест показывает, что в общем случае он возвращается в порядке декларирования.Есть ли конкретные сценарии, о которых вы знаете, где это не так?Кроме того, что является предлагаемой альтернативой?
Подробная версия
Я понимаю документацию MSDN для Type.GetProperties
состояний:
Метод 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
перемещается вверх по цепочке наследования снизу вверх при обнаружении свойств.Это нормально и может быть обработано как таковое.
Вопросы:
- Существуют ли конкретные ситуации, в которых описанное поведение будет отличаться, что я пропустил?
- Если зависитдля заказа не рекомендуется, тогда что является рекомендуемым подходом?
Одним, казалось бы, очевидным решением будет определение пользовательского атрибута, который указывает порядок, в котором свойства должно появиться (аналогично Order
свойству атрибута DataMember
).Что-то вроде:
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
, но поскольку в документации говоритсяне рекомендуется, я искал, чтобы понять, почему и какой другой вариант у меня есть?