0

Say I have a class like...

public abstract class Base
{
    public abstract IAttributes Attributes{ get; set; }
}

public interface IAttributes
{
    string GlobalId { get; set; }
}

And a class like this...

public class ImplementAttributes : IAttributes
{
    public string GlobalId { get; set; } = "";
    public string LocalId { get; set; } = "";
    // Other Properties and Methods....
}

And then I implement it like...

public class Derived: Base
{
    public new ImplementAttributes Attributes { get; set; } 
}

Now, I realise the above will not work because I can't override the property Attributes and if I hide it with new then the following bellow is null because the Base property does not get written.

public void DoSomethingWithAttributes(Base base)
{
    var Foo = FindFoo(base.Attributes.GlobalId);  // Null because its hidden
}

But I would like to be able to access the Base and Derived property attributes eventually like Above.

Can this be accomplished? Is there a better way?

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
NotARobot
  • 978
  • 2
  • 14
  • 36
  • 1
    If you want access to both, you either have to hide it (using `new`) or define another interface and explicitly implement it. Otherwise, you always have the option to cast if you know what the runtime type is. – Jeff Mercado Oct 06 '17 at 16:54
  • I updated my question. I tried new and I think that was the closest to what I am trying to achieve but then when I pass derived objects around as base, then the property is null. – NotARobot Oct 06 '17 at 17:09
  • This does not answer your question? https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-define-abstract-properties – Alexander Toptygin Oct 06 '17 at 17:12
  • @Alexander Toptygin Are you saying, use the setter in the implemented version of the property to write the value to the base? – NotARobot Oct 06 '17 at 17:17
  • You might want to get familiar with [this question](https://stackoverflow.com/questions/4348760/c-sharp-covariant-return-types-utilizing-generics). Your particular use case isn't using generics but it's the same problem. I'll leave it to you to decide on whether this is a duplicate. – Jeff Mercado Oct 06 '17 at 17:24
  • @BrokenRobot - I think I'm misinterpreting your question. – Alexander Toptygin Oct 06 '17 at 17:59

1 Answers1

2

You can use generics:

public abstract class Base<T> where T: IAttributes
{
    public abstract T Attributes{ get; set; }
}

public interface IAttributes
{
    string GlobalId { get; set; }
}

And

public class Derived: Base<ImplementAttributes>
{
    public override ImplementAttributes Attributes { get; set; } 
}

And then:

public void DoSomethingWithAttributes<T>(Base<T> b) where T : IAttributes
{
    var Foo = FindFoo(b.Attributes.GlobalId);
}

You can pass Derived instances without specifying a type parameter explicitly:

Derived d = new Derived();
DoSomethingWithAttributes(d);
Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
  • This is a good answer (+1) and I now have a better understanding of generics. However, it introduces a problem of having to pass a type along with my usage of Base. And I would like to be able to simply access the Interface properties regardless of knowing the derived type. Is this possible? – NotARobot Oct 06 '17 at 17:50
  • You can pass an instance of `Derived` to `DoSomethingWithAttributes` without specifying a type parameter. The type parameter is inferred because `Derived` declares it. – Blorgbeard Oct 06 '17 at 17:52
  • I don't think you can get around the more verbose declaration of `DoSomethingWithAttributes`, though. – Blorgbeard Oct 06 '17 at 17:55
  • Ahh, I am beginning to see. Thank you. – NotARobot Oct 06 '17 at 17:55