Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override a Property with a Derived Type and Same Name C#

I'm trying to override a property in a base class with a different, but derived type with the same name. I think its possible by covarience or generics but am not sure how to do it?

The following code gets the error:

Error 1 'Sun.Cache': type must be 'OuterSpace.Cache' to match overridden member 'OuterSpace.Cache'

public class OuterSpace {
    public virtual OuterSpaceData Data {get; set;}
    public virtual OuterSpaceAnalysis Analysis {get; set;}
    public virtual OuterSpaceCache Cache {get; set;}


    public class OuterSpaceData {
        //Lots of basic Data Extraction routines eg
        public virtual GetData();
    }
    public class OuterSpaceAnalysis {
        //Lots of Generic Analysis on Data routines eg
        public virtual GetMean();
    }
    public class OuterSpaceCache {
        //Lots of Caches of Past Analysis Results:
        public Dictionary<AnalysisType, List<Result>> ResultCache;
    }
}

public class Sun : OuterSpace {
    public override SunData Data {get; set;}
    public override SunAnalysis Analysis {get; set;}
    public override SunCache Cache {get; set;}

    public SunData : OuterSpaceData {
        //Routines to specific get data from the sun eg
        public override GetData();
    }

    public SunAnalysis : OuterSpaceAnalysis {
        //Routines specific to analyse the sun: eg
        public double ReadTemperature();
    }
    public SunCache : OuterSpaceCache {
        //Any data cache's specific to Sun's Analysis
        public Dictionary<AnalysisType, List<Result>> TempCache;
    }
}

public class Moon : OuterSpace {} etc.

For the end result, when I address the "Data" Object of Sun I don't want there to be two Data Objects (Inherited & Base Class) but when I try override the property it requires the Sun variables to be the same type as base class. Eg:

Sun EarthSun = new Sun()
EarthSun.Analyse()  //The OuterSpace Analysis Saves results to Sun Cache:

//Now try use the result:
EarthSun.Cache[0]...

Very similar to this but with derived type instead of string-array: C# Member variable overrides used by base class method

And this answer didn't make much sense to me: How to override member of base class after inheritance in C++

Or perhaps this means its just not possible? Can I Override with derived types?

Help! :) Any work around?

like image 207
JaredBroad Avatar asked Aug 23 '10 19:08

JaredBroad


People also ask

How do you override a derived class method?

In C#, a method in a derived class can have the same name as a method in the base class. You can specify how the methods interact by using the new and override keywords. The override modifier extends the base class virtual method, and the new modifier hides an accessible base class method.

Can we override a property in C#?

An overriding property declaration must specify exactly the same access modifier, type, and name as the inherited property. Beginning with C# 9.0, read-only overriding properties support covariant return types. The overridden property must be virtual , abstract , or override .

Can you override non virtual method C#?

The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member. By default, methods are non-virtual. You cannot override a non-virtual method.

What is derived type in C#?

A derived class, in the context of C#, is a class created, or derived from another existing class. The existing class from which the derived class gets created through inheritance is known as base or super class.


2 Answers

Try going about it with generics. The following class provides a generic base class for OuterSpace with constraints on its parameters that enforce inheritance rules on the property types. I've omitted methods in the small types for clarity.

public class OuterSpace<TData, TAnalysis, TCache>
    where TData : OuterSpaceData
    where TAnalysis : OuterSpaceAnalysis
    where TCache : OuterSpaceCache
{
    public virtual TData Data { get; set; }
    public virtual TAnalysis Analysis { get; set; }
    public virtual TCache Cache { get; set; }
}
public class OuterSpaceData { }
public class OuterSpaceAnalysis { }
public class OuterSpaceCache { }

public class Sun : OuterSpace<SunData, SunAnalysis, SunCache>
{
    public override SunData Data { get; set; }
    public override SunAnalysis Analysis { get; set; }
    public override SunCache Cache { get; set; }
}
public class SunData : OuterSpaceData { }
public class SunAnalysis : OuterSpaceAnalysis { }
public class SunCache : OuterSpaceCache { }

The appeal of this approach is that it permits you to return strongly typed properties and enforce a basic inheritance constraint on the types of those properties. The methods are fully overridable; however, be advised that overriding may well be required to avoid casting issues with the base class implementation.

like image 126
kbrimington Avatar answered Nov 08 '22 02:11

kbrimington


It is not possible the way you want it, exactly.

You can create a "new" property with the same name:

public new SunData Data
{
  get { return (SunData) base.Data; }
  set { base.Data = value; }
}

It's not quite the same thing, but it's probably as close as you're going to get.

Another possible approach would be:

public SunData SunData { get; set; }

public override OuterSpaceData Data
{
  get { return SunData; }
  set { SunData = (SunData)value; }
}

The advantage of this approach is that it does guarantee that it's impossible to put something in your Data property that is not a SunData. The downside is that your Data property is not strongly typed and you have to use the SunData property if you want it statically typed to SunData.

There's an ugly way to get the "best of both worlds" at the expense of being confusing to code and difficult to understand afterwards - by introducing an intermediate derived class that does a 'sealed override' on the base class Data property and redirects to a different protected property with a new name, and then have the ultimate derived class add a 'new' Data property that then calls the intermediate property. It really is an ugly hack, though, and even though I've done it, I wouldn't recommend it.

like image 28
Stuart Avatar answered Nov 08 '22 04:11

Stuart