Инициализировать статический параметр при наследовании в c # - PullRequest
0 голосов
/ 04 марта 2019

У меня есть один базовый класс, который используется для объявления общих структур данных, которые имеют фиксированную длину в блоке данных:

public abstract class FixedLengthDataItem
{

    // a static field here to store the fixed length?

    public sealed void LoadFromBytes(byte[] data)
    {
        // Check the fixed length here

        DoStuff(data, offset);
    }

    protected abstract void DoStuff(byte[] data);
}

Может быть много структур данных, которые имеют фиксированную длину и мое намерениеэто описать их в подклассах.

Я хотел бы знать, есть ли возможность передавать информацию о фиксированной длине при объявлении наследования в дочерних классах:

public class ChildClass : FixedLengthDataItem // Specific syntax here?
{
    public override void DoStuff(byte[] data)
    {
        // Some stuff
    }
}

Я не могу найти такой синтаксис, как : FixedLengthDataItem(2) или : FixedLengthDataItem<2>, который позволил бы установить значение статического поля, которое было бы объявлено в родительском классе и могло бы использоваться для "общей" проверки длины в методе LoadFromBytes (2 в моем примере).

Если нет способа сделать это, какой может быть разумный способ позволить кому-либо писать подклассы, удостоверяясь, что проверка, выполняемая в методе LoadFromBytes, проверяет правильностьвещь?

Я думал о чем-то вроде:

private readonly int _size;
protected FixedLengthDataItem(int size) { _size = size; }

в базовом классе.И:

public ChildClassFoo() : base(2) { } // or
public ChildClassBar() : base(3) { } // etc.

в дочернем классе (ах).Но при этом:

  1. конструктор должен быть объявлен в каждом производном классе,
  2. важнее: в каждом объекте будет существовать поле size, тогда как для всехя думаю, что экземпляры каждого производного класса не очень мудры.

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

Вот один из способов сделать это.Не такой чистый, как шаблоны C ++, но интересный, независимо от того.

public abstract class DataSize
{
    protected DataSize(int size)
    {
        if (size < 0) 
            throw new ArgumentOutOfRangeException("Must be greater than zero.", nameof(size));
        Size = size;
    }

    public int Size { get; }
}  

public abstract class FixedLengthDataItem<TDataSize> 
    where TDataSize : DataSize, new()
{
    public static TDataSize Data { get; } = new TDataSize();

    // a static field here to store the fixed length?

    public void LoadFromBytes(byte[] data)
    {
        // Check the fixed length here
        if (data.Length != Data.Size)
        {
            throw new ArgumentException($"Data has size {data.Length} but a size of {Data.Size} was expected.", nameof(data));
        }

        DoStuff(data);
    }

    protected abstract void DoStuff(byte[] data);
}

public sealed class ItemData345 : DataSize { public ItemDataSize() : base(345) { } }

public sealed class CustomItem : FixedLengthDataItem<ItemData345>
{
    protected override void DoStuff(byte[] data)
    {
        throw new NotImplementedException();
    }
}

Допустим, у вас есть 3-4 класса такого размера, которые он фактически платит за синтаксис.Космическая мудрость - это отдельная история, вам понадобится так много примеров, чтобы это действительно стоило того, но это интересный эксперимент.

0 голосов
/ 04 марта 2019

Для того, что вы описываете, лучше поместить размер в базовый класс, а затем указать его в производных классах, чем использовать какое-либо статическое поле.

Как вы показали в своем вопросе:

public ChildClassFoo() : base(2) { } 
public ChildClassBar() : base(3) { } 

конструктор должен быть объявлен в каждом производном классе

В вашем примере вы объявили два производных класса без конструкторов.

размер поля будет существовать в каждом объекте, в то время как один и тот же размер применяется для всех экземпляров каждого производного класса, что, как я полагаю, не очень разумно.

Это было бы точно, точно смысл помещения этого поляв базовом классе.Если каждому классу, который наследуется от него, нужен размер поля, то то, что вы делаете с базовым классом, гарантирует это.Не имеет значения, если два разных класса имеют одинаковый размер поля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...