Похоже, вы за чем-то вроде нулевого безопасного оператора разборки Groovy, который позволил бы вам написать if (School?.ClassRoom?.Pupil?.Age != null)
- но у C# такого не бывает.
Я боюсь, что вы есть проверить каждое свойство для недействительности, предполагая, что это может быть нуля:
if (School != null && School.ClassRoom != null && School.ClassRoom.Pupil != null
&& School.ClassRoom.Pupil.Age != null)
{
MyMethod(School.ClassRoom.Pupil.Age);
}
Конечно, вы могли бы поместить весь этот if
блок, включающего в себя вызов метода в вспомогательный метод, и просто позвоните.
Предполагается, что он действителен для каждого объекта до be null для начала. Если вы можете создавать свои классы, чтобы нулевые значения даже не разрешались - и вы проверяете это в конструкторах и т. Д., Ваш код, скорее всего, станет намного более чистым.
Следует отметить, что здесь есть два альтернативных подхода: один, предложенный Крисом в другом ответе, заключается в создании объекта «по умолчанию» для каждого свойства; I обычно считают, что лучше всегда требовать «реального» значения, которое должно быть представлено в конструкторе. Объекты по умолчанию без реальных данных могут в конечном итоге вызвать ошибки, которые сложнее отслеживать, чем NullReferenceException
проблемы, так как вы можете долго продолжать использовать «фиктивные» данные в течение длительного времени и просто получить неправильный результат в конце. Есть определенные моменты, когда Правильная вещь, которую нужно сделать, однако - особенно когда дело касается коллекций. Это зависит от ситуации.
EDIT: Саид предложил метод расширения в комментариях. Я полагаю, что это будет что-то вроде: (. Adjust для типов соответственно)
public static int? PupilAgeOrNull(this School school)
{
return school != null &&
school.ClassRoom != null &&
school.ClassRoom.Pupil != null
? school.ClassRoom.Pupil.Age : null;
}
Я определенно предпочитаю идею пытаются держать вещи ненулевым в другом месте, но это будет делать, если вам это нужно , Мне это кажется неправильным. В основе этого чувства кишки лежит тот факт, что вы начинаете с трех или четырех свойств - это похоже на нарушение Law of Demeter для меня. Теперь я не из тех, кто догматичен по поводу таких вещей, но при этом метод расширения на School
чувствует себя слишком специфичным для меня, для такого длинного пути свойств.
Другой вариант - который также несколько противным, IMO - это написать три различные методы расширения:
public static ClassRoom ClassRoomOrNull(this School school)
{
return school == null ? null : school.ClassRoom;
}
public static Pupil PupilOrNull(this ClassRoom classRoom)
{
return classRoom == null ? null : classRoom.Pupil;
}
public static int? AgeOrNull(this Pupil pupil)
{
return pupil == null ? null : pupil.Age;
}
Тогда вы можете написать:
int? age = School.ClassRoomOrNull().PupilOrNull().AgeOrNull();
if (age != null)
{
MyMethod(age);
}
Это означает, что метод расширения на School
не так уж специфичен. У вас все еще есть длинная цепочка вызовов методов, и я все равно попытаюсь перепроектировать, чтобы избежать этой ситуации, если это возможно, но, по крайней мере, нет такой жесткой связи от School
до School.ClassRoom.Pupil.Age
.
Как вы заполняете School.ClassRoom .. данные? Во время заполнения не разрешайте NULL-линии? –
Btw, ваше название не подходит. Нет ничего путающего в том, какое исключение вы получаете. –
Если возможно, я хотел бы иметь возможность продолжить использование нулевых классов, поскольку это часть довольно сложной структуры данных, и если я начну иметь новые экземпляры всех нулей, я думаю, что использование памяти будет проходить через крышу. – Caustix