Guid десериализуется в пустое значение c#
Вот условный код:
internal class Program
{
static void Main(string[] args)
{
var groups = new List<Group>();
var students = new List<Student>();
for (int i = 0; i < 10; i++)
{
groups.Add(new Group());
}
for (int i = 0; i < 300; i++)
{
var group = groups[new Random().Next(0, groups.Count)];
students.Add(new Student($"Student {i}", new Random().Next(0, 100), group));
}
var xmlFormatter = new XmlSerializer(typeof(List<Student>));
using (var file = new FileStream("studentsXML.xml", FileMode.Create, FileAccess.Write))
{
xmlFormatter.Serialize(file, students);
}
using (var file = new FileStream("studentsXML.xml", FileMode.Open))
{
var newStudents = xmlFormatter.Deserialize(file) as List<Student>;
newStudents!.ForEach(s => Console.WriteLine(s));
}
Console.WriteLine("__________________________________________________\n");
Console.WriteLine(students[^1]);
}
}
[Serializable]
public class Student
{
public Guid GuidId { get; }
public string Name { get; set; }
public int Age { get; set; }
public Group Group { get; set; }
public Student()
{
GuidId = new Guid();
Name = string.Empty;
Age = default;
Group = new Group();
}
public Student(string name, int age, Group group)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException(nameof(name));
}
if (age < 0 || age > 130)
{
throw new ArgumentOutOfRangeException(nameof(age));
}
Name = name;
Age = age;
Group = group;
GuidId = Guid.NewGuid();
}
public override string ToString()
{
return $"{GuidId} | {Name} | {Age} | Group: [ {Group} ]";
}
}
[Serializable]
public class Group
{
public int Number { get; set; }
public string Name { get; set; }
public Group()
{
var rnd = new Random();
Number = rnd.Next(1, 100);
Name = $"Group {Number}";
}
public Group(int number, string name)
{
Number = number;
Name = name;
}
public override string ToString()
{
return $"Number: {Number}, Name: {Name}";
}
}
Как я понял, тип Guid сериализуется не правильно (или десериализуется), потому что на выходе в консоле у меня пустое значение Guid.

Почему так происходит? И еще вопрос, почему для сериализации определенного типа необходимо, чтобы у этого типа обязательно был конструктор без параметров?
Ответы (1 шт):
Сериализация - это процесс "сохранения" данных программы в текстовый формат. Десериализация - это процесс извлечения данных из какого-то условно текстового формата с переносом в исполняемый код. Это может быть xml как у тебя, так и json или вообще бинарный файлик.
Логика такая, что в процессе сериализации система смотрит что у тебя там за объекты, какие поля и переменные у него имеются и записывает в текстовый формат. Типа твоего xml.
А при десериализации сначала создаётся пустой объект без данных - для этого и нужен конструктор без параметров. В процессе система пытается самостоятельно создать пустой экземпляр класса, но она сама по себе "тупая" и не может догадаться что куда пихать в конструктор. (Это ответ на то, для чего нужен конструктор без параметров)
И вот после создания пустого экземпляра класса система начинает заполнять поля и переменные в нём. И тут как раз возникает проблема. GuidId у тебя имеет только get;, без set; То есть он записывается при сериализации, но не может задаться в процессе десериализации.
Так что либо добавь set;
public Guid GuidId { get; set; }
Либо, если тебе нужна защита этого поля - сделай приватную сериализуемую переменную и через неё осуществляй запись.