简体   繁体   中英

C# polymorphism and templates

This question may have been asked already, but I don't know the correct question to ask in order to find the answer.

I am attempting to make a set of classes (tags) that hold a value and allow other components to access the value.

The value is generic, which will allow you to create a Tag of any type. However I need to be able to hold the tags within a list or other data structure to allow the component to have multiple tags of multiple types.

  public abstract class BaseTag
  {
    protected object _value;
    public ushort DataQuality { get; protected set; }
    public virtual object Value => _value;
    public abstract void SetValue(object value, ushort dataQuality = 0);
  }

  public class Tag<T> : BaseTag
  {
    public new T Value
    {
      get => (T)_value;
      private set
      {
        _value = value;
      }
    }
    public override void SetValue(object value, ushort dataQuality = 0)
    {
      Monitor.Enter(_tagSync);

      try
      {
        //If value or quality haven't changed, then do nothing
        if (EqualityComparer<T>.Default.Equals((T)_value, (T)value) && dataQuality == DataQuality)
          return;

        DataQuality = dataQuality;
        Value = (T)value;
      }
      finally
      {
        Monitor.Exit(_tagSync);
      }
    }
  }

I don't even really know if I am asking the correct question still.

Can anyone help

How do I get the ability to have a List tags; tags[0].Value <- would like this to call the child value, but it doesn't, it returns the basetag._value, but of type object, not type

Is there an easier better way to make this happen?

do you really need the BaseTag class?

You can convert it to the interface and do with explicit interface declaration like below:

public interface IBaseTag
{
    object Value { get; }
    ushort DataQuality { get; }
}

public class Tag<T> : IBaseTag
{
    public T Value { get; set; }

    object IBaseTag.Value => Value; // explicit interface implementation

    public ushort DataQuality { get; protected set; }

    public virtual void SetValue(T value, ushort dataQuality = 0)
    {
        //If value or quality haven't changed, then do nothing
        if (EqualityComparer<T>.Default.Equals(Value, value) && dataQuality == DataQuality)
            return;

        DataQuality = dataQuality;
        Value = (T)value;
    }
}

I've skipped the _tagSync functional.

Then you can get the

var b = new Tag<int>(); //child
IBaseTag a = b; //parent

//a.Value and b.Value are both accessible and can be used
if (b.Value.Equals(a.Value) && a.DataQuality == b.DataQuality)
    return;

You can use the IBaseTag.Value or Tag<>.Value in the same time according to the dependency isolation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM