0

I have an abstract base class:

public abstract class BaseObject
{
    internal abstract string DatabaseTableName { get; }
    internal abstract string ObjectType { get; }
 
    // other class members not important
}

That has two abstract subclasses -- the only difference is one has a 32-bit Id and the other a 64-bit Id:

public abstract class BaseObject32 : BaseObject
{
    public int Id { get; private set; }
 
    // other class members not important
}

public abstract class BaseObject64 : BaseObject
{
    public long Id { get; private set; }

    // other class members not important
}

I would like to make it so that any class that inherits BaseObject32 or BaseObject64 must implement these two properties, but then those properties should be accessible via the BaseObject class.

In other words, I'd like to do this:

public class Cat : BaseObject32 
{
    DataBaseTableName => "animals.cat";
    ObjectName => "Cat";
}

And then be able to do this:

BaseObject c = new Cat();
string x = c.DatabaseTableName;

I'm clearly missing something. I've tried addding "new" and "override" within my Cat class, but it keeps saying I need to implement the inherited class member. Here is a rough idea of what I want in each inheriting class.

private const string _ObjectType = "Cat";
private const string _DataBaseTableName = "animals.cat";

internal override string ObjectType => _ObjectType;
internal override string DatabaseTableName => _DataBaseTableName;

I am hopeful this is possible and I'm just missing something...

Rand Random
  • 7,300
  • 10
  • 40
  • 88
Hambone
  • 15,600
  • 8
  • 46
  • 69
  • Do you mean you just need `internal override string DatabaseTableName => "animals.cat";`? I'm confused, since that seems to do exactly what you need. e.g. https://dotnetfiddle.net/EKIu1R – DavidG Jun 13 '23 at 21:03
  • @DavidG - I tried that, but I get this: CS0534 'Cat does not implement inherited abstract member ... – Hambone Jun 13 '23 at 21:07
  • I just included a running example in my first comment – DavidG Jun 13 '23 at 21:07
  • @DavidG -- that sure works on fiddle, but with the identical constructs I'm still getting that message. Interestingly when I "implement abstract class" it creates the stubs but still gives me that error. I'll study your example more -- it's exactly what I want but I'm not getting the same results. I'm on Framework 4.8. That shouldn't matter, right? – Hambone Jun 13 '23 at 21:16
  • Does it work with `internal override string DatabaseTableName { get { return "animals.cat"; } }` – DavidG Jun 13 '23 at 21:18
  • Look at my answer again. Is that not what you want? – A.B. Jun 13 '23 at 21:20
  • Final follow-up... the issue for reasons completely unknown to me the program would not compile with the `internal` modifier. I want these to be internal, not public. However, when I changed the properties to `public` it compiles. Wow, I'm confused. Thanks to all who helped diagnose and answer. – Hambone Jun 13 '23 at 22:03

2 Answers2

2

Normally you would simply do this:

public class Cat : BaseObject32
{
    internal override string DatabaseTableName => "animals.cat";
    internal override string ObjectType => "Cat";
}

However, since you are using an older version of C#, you may not be able to use a lamda expression for a property (i.e. expression-bodied members) so need to use the older syntax:

public class Cat : BaseObject32
{
    internal override string DatabaseTableName { get { return "animals.cat"; } }
    internal override string ObjectType { get { return "Cat"; } }
}
DavidG
  • 113,891
  • 12
  • 217
  • 223
  • FYI Lambdas do work for properties in 4.8... okay, so I took this and put it into a clean project on 4.8, and it's working perfectly. So something is amiss with my actual project, but clearly your suggestion works. My initial error was I was referencing the two properties in BaseObject32 and BaseObject64, but I removed those and am still having issues. Regardless, you have demonstrated a working solution. Thank you! – Hambone Jun 13 '23 at 21:56
-2

Just use Generics:

public abstract class BaseObject<T> where T: struct 
{
    public abstract T Id { get; set; }
    public abstract string DatabaseTableName { get; }
    public abstract string ObjectType { get; }
}

public abstract class BaseObject32 : BaseObject<int>
{
    public override int Id { get; set; }
}

public abstract class BaseObject64 : BaseObject<long>
{
    public override long Id { get; set; }
}

public class Cat : BaseObject32
{
    public override string DatabaseTableName => "animals.cat";
    public override string ObjectType => "Cat";
}

BaseObject<int> c = new Cat();
string x = c.DatabaseTableName;

If you want to limit the constraint more precisely, see this topic too: Is there a constraint that restricts my generic method to numeric types?

A.B.
  • 2,374
  • 3
  • 24
  • 40
  • 2
    Yeah, pretty sure OP doesn't care about the Id property here anyway – DavidG Jun 13 '23 at 21:08
  • Yeah, sorry... the Id is not super relevant; it was only to illustrate why I have the abstract subclasses. BaseObject has a lot of class members, and BaseObject32 and 64 basically only add this one property. – Hambone Jun 13 '23 at 21:10
  • I added the 2 properties what you wanted. – A.B. Jun 13 '23 at 21:18