Значение поля, унаследованное от C #, смешивается со значением поля базового класса - PullRequest
1 голос
/ 31 января 2012

Я пытаюсь сериализовать экземпляры MyClass в файл XML, по одному за раз.Каждый экземпляр имеет свойство int с именем 'ID'.В целевом файле уже есть некоторые элементы того же типа, и я добавляю новые элементы после них.Мне бы хотелось, чтобы значение идентификатора экземпляра, который будет вставлен, было на 1 больше, чем самый большой существующий элемент в XML.

У меня есть следующий общий класс:

public class ContentDataManager<T> where T : MyBaseClass
{
    private static string _contentLocation = "Content/Data/";
    private const string DEFAULT_FILEPATH = "data.xml";

    public static int GetNextId(string filepath = DEFAULT_FILEPATH)
    {
        var allData = DeserializeAll(filepath);
        int largestId = 0;
        foreach (T data in allData)
        {
            if (data.ID > largestId)
            {
                largestId = data.ID;
            }
        }
        return largestId + 1;
    }
//...
}

I'mиспользуя этот класс следующим образом:

public class MyClass : MyBaseClass
{
    public string Name;
    public float Size;
    public new int ID;

    public static MyClass CreateNew(string name, float size)
    {
        MyClass newClass = new MyClass();
        newClass.Name = name;
        newClass.Size = size;
        newClass.ID = ContentDataManager<MyClass>.GetNextId(DefaultFilepath);
        return newClass;
    }

MyBaseClass выглядит следующим образом:

public abstract class MyBaseClass
{
    //...
    [ContentSerializerIgnore]
    public int ID = 0;
}

Проблема в том, что в цикле foreach метода ContentDataManager.GetNextId (...) естьесли утверждение, которое на самом деле не работает должным образомКогда я отлаживал, я добавил два наблюдения: «data» и «data.ID». Вот интересная часть: Отслеживание «data» показывает, что значение свойства ID равно 1. В то же время, «Свойство data.ID 'показывает значение 0.

Я уверен, что эта ошибка связана с наследованием.Как мне изменить свой код, чтобы я не получил эту ошибку?

Ответы [ 2 ]

2 голосов
/ 31 января 2012

Вам необходимо удалить эту строку:

public new int ID;

Из того, что вы показали, нет необходимости в отдельном идентификаторе в производном классе, базовый будет хорошо работать. Конечно, вам также нужно удалить атрибут ContentSerializerIgnore, если вы хотите, чтобы ID был сериализован.

Вот пример, демонстрирующий, что когда вы используете ключевое слово 'new' для объявления члена, вы создаете совершенно не связанный элемент для члена базового класса.

using System;

namespace Test
{
    abstract class  Base
    {
        public string Data;
    }

    class Derived : Base
    {
        // this is a separate field, has nothing in common with the base class field but name
        new public string Data;
    }

    class Program
    {
        static void Main(string[] args)
        {
            Derived test = new Derived();

            //Let's set the Data field in the derived class
            test.Data = "Derived";

            //Now let's set this field in the base class
            Base cast = test;
            cast.Data = "Base";

            //We can see that the feild in the derived class has not changed
            //This will print 'Derived'
            Console.WriteLine(test.Data);

            // Just to make sure that a new object has not been constructed by a miracale
            // let's pass our object to a function that will display the Data field from
            // the base class
            Test(test);
        }

        static void Test(Derived test)
        {
            // When called from the Main above this will print 'Base'
            Console.WriteLine(((Base)test).Data);            
        }
    }
}
1 голос
/ 31 января 2012

Проблема в том, что вы указали where T : MyBaseClass. Это означает, что переменная цикла foreach data будет иметь тип MyBaseClass. Поэтому единственным доступным значением data.ID будет версия базового класса.

См. Это описание об этом.

Вам придется либо набрать data, чтобы иметь тип MyClass, либо всегда использовать поле ID базового класса (именно это и предлагает zespri ).

...