Inheritance problem in C# - c#

I'm refactoring some code and want to classes a bit higher in the inheritance chain be a bit more strict with their parameters. As I'm not sure I'm explaining this correctly, here's what I've got:
public interface ISvdPredictor
{
List<string> Users { get; set; }
List<string> Artists { get; set; }
float PredictRating(ISvdModel model, string user, string artist);
float PredictRating(ISvdModel model, int userIndex, int artistIndex);
}
ISvdPredictor uses ISvdModel:
public interface ISvdModel
{
float[,] UserFeatures { get; set; }
float[,] ArtistFeatures { get; set; }
}
Now I want to implement another variation:
public interface IBiasSvdPredictor : ISvdPredictor
{
float PredictRating(IBiasSvdModel model, string user, string artist);
float PredictRating(IBiasSvdModel model, int userIndex, int artistIndex);
}
Which uses IBiasSvdModel which derives from ISvdModel:
public interface IBiasSvdModel : ISvdModel
{
float GlobalAverage { get; set; }
float[] UserBias { get; set; }
float[] ArtistBias { get; set; }
}
IBiasSvdPredictor will not work with ISvdModel.
The problem is that when I implement IBiasSvdPredictor I'd have to implement 2 pairs of PredictRating methods. One from ISvdPredictor and the other from IBiasSvdPredictor. What do I need to do to be able to just implement those from IBiasSvdPredictor?
I've tried generics as well, but couldn't restrict the PredictRating for BiasSvdPredictor to IBiasSvdModel using the where directive. I may be doing this all wrong so any suggestion might help. I think you get what I'm trying to do.
EDIT: If anyone needs more context see https://github.com/gligoran/RecommendationSystem. I'm writing this code for my thesis for BSc.

You could use generics and constraints.
public interface ISvdModel
{
float[,] UserFeatures { get; set; }
float[,] ArtistFeatures { get; set; }
}
public interface IBiasSvdModel : ISvdModel
{
float GlobalAverage { get; set; }
float[] UserBias { get; set; }
float[] ArtistBias { get; set; }
}
public interface ISvdPredictor<in TSvdModel>
where TSvdModel : ISvdModel // Require that TSvdModel implements ISvdModel
{
List<string> Users { get; set; }
List<string> Artists { get; set; }
float PredictRating(TSvdModel model, string user, string artist);
float PredictRating(TSvdModel model, int userIndex, int artistIndex);
}
// I would actually avoid declaring this interface. Rather, see comment on the class.
public interface IBiasSvdPredictor : ISvdPredictor<IBiasSvdModel> { }
class BiasSvdPredictor : IBiasSvdPredictor // Preferred : ISvdPredictor<IBiasSvdModel>
{
// ...
public float PredictRating(IBiasSvdModel model, string user, string artist) { }
public float PredictRating(IBiasSvdModel model, int userIndex, int artistIndex) { }
}

The interface should have one method, PredictRating. I wouldn't have two interfaces that have the same method to implement. Confusing.
Create an abstract class that implements your interface. Make PredictRating a virtual method so inheritors can override as they see fit. You could even do a default implementation on the abstract class.
One interface, One abstract class. N concrete class that implement PredictRating as they see fit.
public interface Demo
{
int PredictRating(int param1);
}
public abstract class AbstractDemo : Demo
{
public virtual int PredictRating(int param1)
{
return param1 + 1;
}
}
public class ClassDemo1 : AbstractDemo
{
//This guy uses AbstractDemo Predict Rating
public override int PredictRating(int param1)
{
return base.PredictRating(param1);
}
}
public class ClassDemo2 : AbstractDemo
{
//This guy overrides the predict rating behavior
public override int PredictRating(int param1)
{
return param1 + 2;
}
}

You have to implement all four methods. They have different signatures and thus are considered to be different. However, you can have one delegate to the other, and sometimes using explicit implementation helps with that.
public class Foo : IBiasSvdPredictor {
public float PredictRating(IBiasSvdModel, string user, string artist) { .... }
// this is an expicit implementation of ISvdPredictor's method. You satisfy
// the interface, but this method is not a public part of the class. You have to
// cast the object to ISvdPredictor in order to use this method.
float ISvdPredictor.PredictRating(ISvdModel model, string user, string artist) {
this.PredictRating((IBiasSvdModel)model, user, artist);
}
}
This of course will not work if the ISvdModel is not actually an IBiasSvdModel.

You can use explicit interface implementation to hide the ones from ISvdPredictor, but you should implement them all or have a base abstract class to handle them.

I'd have to implement 2 pairs of PredictRating methods.
Of course you do. What did you expect?
If your IBiasSvdPredictor must take a IBiasSvdModel in its PredictRating method, than IBiasSvdPredictor is not an ISvdPredictor (because it cannot take a ISvdModel as the first parameter to PredictRating) and inheriting IBiasSvdPredictor from ISvdPredictor is the wrong choice.
In my opinion, you should simply keep the interfaces separate and not inherit one from the other.

Without having a full understanding of your object model (so this may not actually apply in your situation), it seems like maybe ISvdModel shouldn't be part of the interface definition. It seems more like it's an implementation detail, not necessarily part of the contract you're trying to enforce. To me it makes more sense to pass ISvdModel (or IBiasSvdModel) into the constructor of your implementation class, not have it as part of your ISvdPredictor interface. Then you wouldn't need 2 separate interface definitions at all, you would just have 2 implementations of the single interface.
You might even be able to take it one step further; if the only difference between ISvdPredictor and IBiasSvdPredictor is that one uses a ISvdModel and the other uses a IBiasSvdModel, you wouldn't even need 2 implementations, just one, and you would pass in the correct instance of ISvdModel for each situation. This is a design pattern called Inversion of Control, specifically using Dependency Injection, and is very powerful to achieve higher levels of code reuse in your programs.

Related

How to derive from/implement a C# class hierarchy in without code duplication

I am faced with a C# design problem that C#'s limitations are making hard to achieve. I need some sort of design pattern/strategy to rescue me.
I must create the archetypical set of abstract shape classes: Base class Shape with derived classes LineShape, RectShape, etc. Specific implementations will derive from these. The problem is that I really need to use classes here, not interfaces and this is forcing me to duplicate a lot of code.
To illustrate:
public abstract class Shape
{
public abstract int Id { get; } // Unique ID
public abstract string Name { get; set; } // Shape name. Defaults to the type of shape
public abstract bool IsLocked { get; set; } // May the user change this shape in any way?
}
public abstract class LineShape : Shape
{
public abstract Point P1 { get; set; }
public abstract Point P2 { get; set; }
}
public abstract class CircleShape : Shape
{
public abstract Point Center { get; set; }
public abstract double Radius { get; set; }
}
When I start creating the derived implementations (LineImpl, CircleImpl, etc), I find that the implementations of the Shape functions are identical for all the Impl classes, yet specific enough that I cannot implement them in the abstract Shape class itself.
So I need to find a way to share a common implementation of these function in my derived hierarchy.
In other words LineImpl must derive from LineShape. CircleImpl must derive from CircleShape, etc. I cannot find a way to insert a ShapeImpl in there to handle the boiler plate stuff. So I am forced to implement all those Shape functions over and over again, once in each Impl shape type.
I tried using generics to get my way out of this but unfortunately a generic class cannot specify its base class with a generic argument. In other words, the following approach (which I might do in C++) does not work in C#
public class ShapeImpl<TBase> : T where T : Shape { ... boiler plate implemented here)...}
public class LineImpl : ShapeImpl<LineShape> { }
public class CircleImpl : ShapeImpl<CircleShape> { }
So I am at a loss. Is there some C# trick or design pattern that can get me out of this? Or am I forced to implement the same functions multiple times?
yet specific enough that I cannot implement them in the abstract Shape class itself.
You also mentioned:
I find that the implementations of the Shape functions are identical for all the Impl classes
I think that this is classic case of over-thinking for future implementation. if you say- the implementation is identical for all classes, I wouldn't bother too much over thinking for something in the future that may never arrive.
But, if you insist, you may implement it in the following way:
public abstract class Shape
{
public abstract int Id { get; } // Unique ID
public abstract string Name { get; set; } // Shape name. Defaults to the type of shape
public abstract bool IsLocked { get; set; } // May the user change this shape in any way?
public abstract void Foo();
}
public abstract class SepcificShape : Shape
{
protected virtual void FooSpecific()
{
Console.WriteLine("Specific Implementation");
}
}
public abstract class LineShape : SepcificShape
{
public abstract Point P1 { get; set; }
public abstract Point P2 { get; set; }
}
public class LineImp : SepcificShape
{
public override int Id { get; }
public override string Name { get; set; }
public override bool IsLocked { get; set; }
public override void Foo()
{
base.FooSpecific();
}
}
The only way to achieve something similar to multiple inheritance in C# I can think of would be to use default interface implementations, e.g. like this:
interface IShapeSdk
{
string GetNameSdk() => "Shape SDK name";
}
abstract class Shape
{
public abstract string GetName();
}
class ShapeImpl : Shape, IShapeSdk
{
public override string GetName()
{
return ((IShapeSdk)this).GetNameSdk();
}
}
This way all shapes will inherit from Shape, but only the external-SDK-shapes will inherit the common logic defined in IShapeSdk.
Not the cleanest approach, and a lot of C# developers are against the usage of this relatively new feature (which by the way is available only in C# 8 and above and .NET Core 3.0 and above).

Trying to understand C# nested interfaces

I'm trying to get a simple set of interfaces to be nested so I can enforce some members on derived classes.
public enum Category { Mental, Physical, Technical }
interface IAbilities
{
List<IAbility> Abilities { get; set; }
}
interface IAbility
{
Category Category { get; }
int Value { get; set; }
string Descritpion { get; set; }
}
public class MentalAbilities : IAbilities
{
// This is what I want so that "Abilities" is accessible
public List<MentalAbility> Abilities { get; set; }
// This is what Intellisense generates, cannot be set to public
//List<IAbility> IAbilities.Abilities { get; set; }
}
public class MentalAbility : IAbility
{
public Category Category { get; } category
public int Value { get; set; }
public string Descritpion { get; set; }
}
Of course the Intellisense generated bit compiles, but "Abilities" is not accessible from a class instance because it can't be set to public.
The bit I want tells me `'MentalAbilities' does not implement interface member 'IAbilities.Abilities'. 'MentalAbilities.Abilities' cannot implement 'IAbilities.Abilities' because it does not have the matching return type of List<IAbility>.
I don't understand since "MentalAbility" is derived from the "IAbility" interface so that should fulfill the contract.
(I'm skipping over the "x is less accessible than y" error because you already worked out you can make your interfaces public - sure you can appreciate how anything has to be at least as accessible as it's use)
Re your "does not implement" error:
I understand your problem, but you've kinda got it upside down
I see that you want to ensure, in your MentalAbilities.Abilities list, someone only puts MentalAbility objects.. and they implement IAbility so it should satisfy the "object is a IAbilities and has a list which contains only things that implement IAbility" rules, right?
Alas, no. This the pretty much the opposite of what inheritance or interface implementation is for.
The idea behind inheritance is that you can say "this thing can be any type at all as long as it has these common aspects and I will treat it in the common way". By declaring such that List<IAbility> you're saying "objects in this list just have to implement IAbility and then I'll be able to deal with them" - it could be a MentalAbility, or a PhysicalAbility - doesn't matter
You cannot then constrain the list to only containing MentalAbility via the inheritance/implements mechanism, nor should you because it's opposite of what it is for- going from "I can deal with anything so long as it implements X" to "I will only deal with something if it is, or is a subtype of, Y" is the opposite of what was claimed earlier. You're saying that MentalAbilities can only deal with the list contents if they're MentalAbility, when you earlier said it could deal with anything that was an IAbility
If you want to enforce that MentalAbilities only contains MentalAbility you'll have to declare it as List<IAbility> and look at the type of the IAbility you're given in the set and refuse to add it if if it's not a MentalAbility, but if other developers use your code they will be very confused - "what? It says I'm allowed to use anything that implements IAbility, and my TigerAbility does just that.. why am I getting an exception that it must be a MentalAbility? Why did this developer even use a List(IAbility) if I'm not allowed to sling any IAbility I like into it?" - it's also no longer a compile time thing, but a runtime one and that's a big risk
I think you need to decide if you're going to be able to treat these things in a generic way i.e. can your AbilitiesProcessor implement IAbilities and have a list of IAbility and process them regardless of actual type, or not. If it can't, and you're going to have a MentalAbilities class that can only deal with MentalAbility that's fine, and it can have a List<MentalAbility> all it wants, fellow developers won't mistakenly put a TigerAbility into it, but it won't implement the IAbilities interface
I'm trying to get a simple set of interfaces to be nested so I can enforce some members on derived classes.
Your main issue here is that defined the two interfaces as private by default. That's what is preventing you from creating public List<IAbility> Abilities { get; set; } inside MentalAbilities.
Actually, the property public List<MentalAbility> Abilities { get; set; } is also preventing you as you can't have a property of the same name defined twice.
The big question here would be what would be the point of allowing MentalAbilities the ability to set a List<IAbility> since that would mean setting any type of ability.
Ideally MentalAbilities should only have a single list of MentalAbility that it contains - and it should only be read-only. In fact, most of your interfaces should be read-only.
Here's what you should do:
Start with these interfaces:
public interface IAbilities<A> where A : IAbility
{
List<A> Abilities { get; }
}
public interface IAbility
{
Category Category { get; }
int Value { get; }
string Description { get; }
}
Notice the IAbilities<A> interface uses a generic type A that you can fill in later.
Next, let's set up some base classes that simplify the implementation of each specific class.
public abstract class AbilitiesBase<A> : IAbilities<A> where A : IAbility
{
public List<A> Abilities { get; protected set; }
}
public abstract class AbilityBase : IAbility
{
public abstract Category Category { get; }
public abstract int Value { get; }
public abstract string Description { get; }
}
Now the final classes are simple:
public class MentalAbilities : AbilitiesBase<MentalAbility> { }
public class MentalAbility : AbilityBase
{
public override Category Category => Category.Mental;
public override int Value => 42;
public override string Description => "Mental!";
}
There's nothing to implement in MentalAbilities - the base class took care of that - but it does have a List<MentalAbility> Abilities { get; } property.
MentalAbility is also neatly set up to enforce you to override the properties.
Now, if you actually wanted still have a List<IAbility> Abilities { get; } property then there's an easy way to do that by writing these two interfaces:
public interface IAbilities
{
List<IAbility> Abilities { get; }
}
public interface IAbilities<A> : IAbilities where A : IAbility
{
new List<A> Abilities { get; }
}
This forces a change to AbilitiesBase like this:
public abstract class AbilitiesBase<A> : IAbilities<A> where A : IAbility
{
public List<A> Abilities { get; protected set; }
List<IAbility> IAbilities.Abilities => this.Abilities.Cast<IAbility>().ToList();
}
The List<IAbility> IAbilities.Abilities property generates a copy of the public List<A> Abilities { get; protected set; } property, but that's what you want to prevent anyone adding the wrong type of ability to the original list.
Personally, I would go with this instead:
public interface IAbilities
{
IEnumerable<IAbility> Abilities { get; }
}
public interface IAbilities<A> : IAbilities where A : IAbility
{
new List<A> Abilities { get; }
}
public abstract class AbilitiesBase<A> : IAbilities<A> where A : IAbility
{
public List<A> Abilities { get; protected set; }
IEnumerable<IAbility> IAbilities.Abilities => this.Abilities.Cast<IAbility>();
}
What you are stuck with is called implicit and explicit implementation of interfaces in C#. If you define your class member like this:
public List<MentalAbility> Abilities { get; set; }
you are implementing IAbilities implicitly and you need to write public with it. If you define your class member as
List<IAbility> IAbilities.Abilities { get; set; }
you have implemented IAbilities explicitly, in which case it can be private.
While we are here, I see no point in defining an interface IAbilities. You should simply use IEnumerable<IAbility> anywhere you want to use IAbilities, which is literally providing no value in your code.

Default implementation of a method for C# interfaces?

Is it possible to define an interface in C# which has a default implementation? (so that we can define a class implementing that interface without implementing that particular default method).
I know extension methods (as explained in this link for example). But that is not my answer because having a method extension like the following, the compiler still complains about implementing MyMethod in MyClass:
public interface IMyInterface
{
string MyMethod();
}
public static class IMyInterfaceExtens
{
public static string MyMethod(this IMyInterface someObj)
{
return "Default method!";
}
}
public class MyClass: IMyInterface
{
// I want to have a default implementation of "MyMethod"
// so that I can skip implementing it here
}
I am asking this because (at least as far as I understand) it is possible to do so in Java (see here).
PS: having an abstract base class with some method is also not my answer simply because we don't have multiple inheritance in C# and it is different from having a default implementation for interfaces (if possible!).
C# v8 and above allows concrete method implementation in interfaces as well. This will allow your concrete implementation classes to not break when you change the interfaces being implemented in future.
So something like this is now possible:
interface IA
{
void NotImplementedMethod(); //method having only declaration
void M()
{
WriteLine("IA.M");
}//method with declaration + definition
}
Please refer to this GitHub issue # 288. Also Mads Torgersen talks about this feature at length in this channel 9 video.
MS Docs - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods
I develop games so I often want to have common function for all implementations of an interface but at the same time allow each implementation to do its own thing as well, much like a subclass' virtual / override methods would function.
This is how I do it:
public class Example
{
void Start()
{
WallE wallE = new WallE();
Robocop robocop = new Robocop();
// Calling Move() (from IRobotHelper)
// First it will execute the shared functionality, as specified in IRobotHelper
// Then it will execute any implementation-specific functionality,
// depending on which class called it. In this case, WallE's OnMove().
wallE.Move(1);
// Now if we call the same Move function on a different implementation of IRobot
// It will again begin by executing the shared functionality, as specified in IRobotHlper's Move function
// And then it will proceed to executing Robocop's OnMove(), for Robocop-specific functionality.
robocop.Move(1);
// The whole concept is similar to inheritence, but for interfaces.
// This structure offers an - admittedly dirty - way of having some of the benefits of a multiple inheritence scheme in C#, using interfaces.
}
}
public interface IRobot
{
// Fields
float speed { get; }
float position { get; set; }
// Implementation specific functions.
// Similar to an override function.
void OnMove(float direction);
}
public static class IRobotHelper
{
// Common code for all IRobot implementations.
// Similar to the body of a virtual function, only it always gets called.
public static void Move(this IRobot iRobot, float direction)
{
// All robots move based on their speed.
iRobot.position += iRobot.speed * direction;
// Call the ImplementationSpecific function
iRobot.OnMove(direction);
}
}
// Pro-Guns robot.
public class Robocop : IRobot
{
public float position { get; set; }
public float speed { get; set;}
private void Shoot(float direction) { }
// Robocop also shoots when he moves
public void OnMove(float direction)
{
Shoot(direction);
}
}
// Hippie robot.
public class WallE : IRobot
{
public float position { get; set; }
public float speed { get; set; }
// Wall-E is happy just moving around
public void OnMove(float direction) { }
}
Short Answer:
No, you cannot write implementation of method in interfaces.
Description:
Interfaces are just like contract ,so that the types that will inherit from it will have to define implementation, if you have a scenario you need a method with default implementation, then you can make your class abstract and define default implementation for method which you want.
For Example:
public abstract class MyType
{
public string MyMethod()
{
// some implementation
}
public abstract string SomeMethodWhichDerivedTypeWillImplement();
}
and now in Dervied class:
public class DerivedType : MyType
{
// now use the default implemented method here
}
UPDATE (C# 8 will have support for this):
C# 8 will allow to have default implementation in interfaces
Not directly, but you can define an extension method for an interface, and then implement it something like this
public interface ITestUser
{
int id { get; set; }
string firstName { get; set; }
string lastName { get; set; }
string FormattedName();
}
static class ITestUserHelpers
{
public static string FormattedNameDefault(this ITestUser user)
{
return user.lastName + ", " + user.firstName;
}
}
public class TestUser : ITestUser
{
public int id { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string FormattedName()
{
return this.FormattedNameDefault();
}
}
Edit*
It is important that the extension method and the method that you are implementing are named differently, otherwise you will likely get a stackoverflow.
it is possible in C# 8.0. You can add a method with default implementation. You will have to change your target framework version to latest to use this feature.
As a newbe C# programmer I was reading through this topic and wondered if the following code example could be of any help (I don't even know if this is the proper way to do it). For me it allows me to code default behavior behind an interface. Note that I used the generic type specifiction to define an (abstract) class.
namespace InterfaceExample
{
public interface IDef
{
void FDef();
}
public interface IImp
{
void FImp();
}
public class AbstractImplementation<T> where T : IImp
{
// This class implements default behavior for interface IDef
public void FAbs(IImp implementation)
{
implementation.FImp();
}
}
public class MyImplementation : AbstractImplementation<MyImplementation>, IImp, IDef
{
public void FDef()
{
FAbs(this);
}
public void FImp()
{
// Called by AbstractImplementation
}
}
class Program
{
static void Main(string[] args)
{
MyImplementation MyInstance = new MyImplementation();
MyInstance.FDef();
}
}
}
C# 11 feature - Now official:
Static virtual members in interfaces
Docs saying:
C# 11 and .NET 7 include static virtual members in interfaces.
This feature enables you to define interfaces that include overloaded
operators or other static members.
Once you've defined interfaces with static members, you can use those interfaces as constraints to create generic types that use operators or other static methods.
So you can:
Define interfaces with static members.
Use interfaces to define classes that implement interfaces with operators defined.
Create generic algorithms that rely on static interface methods.
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/static-virtual-interface-members
Prerequisites
You'll need to set up your machine to run .NET 7, which supports C# 11

Generic Interface inheriting Non-Generic One C#

This is class design question.
I have main abstract class
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestriction<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestriction<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestriction<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}
BlockRule rule=new BlockRule();
TimeRestriction t=new TimeRestriction();
AgeRestriction a=new AgeRestriction();
rule.Restrictions.Add(t);
rule.Restrictions.Add(a);
I have to use non-generic Interface IRestriction just to avoid specifying generic type T in main abstract class. I'm very new to generics. Can some one let me know how to better design this thing?
Your approach is typical (for example, IEnumerable<T> implements IEnumerable like this). If you want to provide maximum utility to consumers of your code, it would be nice to provide a non-generic accessor on the non-generic interface, then hide it in the generic implementation. For example:
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions { get; set; }
}
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T:struct
{
// hide IRestriction.Limit
new T Limit {get;}
}
public abstract class RestrictionBase<T> : IRestriction<T>
where T:struct
{
// explicit implementation
object IRestriction.Limit
{
get { return Limit; }
}
// override when required
public virtual T Limit { get; set; }
}
public class TimeRestriction : RestrictionBase<TimeSpan>
{
}
public class AgeRestriction : RestrictionBase<TimeSpan>
{
}
public class BlockRule : AbstractBlockRule
{
public override List<IRestriction> Restrictions { get; set; }
}
I also showed using a base restriction class here, but it is not required.
The runtime treats IRestriction<TimeSpan> and IRestriction<int> as different distinct classes (they even have their own set of static variables). In your case the only classes common to both IRestriction<TimeSpan> and IRestriction<int> in the inheritance hierarchy are IRestriction and object.
So indeed, having a list of IRestriction is the only sensible way to go.
As a side note: you have a property Limit in there that you might want to access regardless of whether you're dealing with an IRestriction<TimeSpan> or IRestriction<int>. What I would do in this case is to define another property object Limit { get; } on IRestriction, and hide it in the actual implementation. Like this:
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T : struct
{
new T Limit { get; set; }
}
public class TimeRestriction : IRestriction<TimeSpan>
{
public TimeSpan Limit { get; set; }
// Explicit interface member:
// This is hidden from IntelliSense
// unless you cast to IRestriction.
object IRestriction.Limit
{
get
{
// Note: boxing happens here.
return (object)Limit;
}
}
}
This way you can access Limit as object on all your IRestriction when you don't care what type it is. For example:
foreach(IRestriction restriction in this.Restrictions)
{
Console.WriteLine(restriction.Limit);
}
Interfaces are contracts that need to be followed by the entity that implements the contract.
You have created two contract with the same name IRestriction
As far as I can see, what you are basically may need is a flag for classes that can be restricted, which should implement the IRestriction non-generic interface.
The second interface seems to be restrictable objects that also contain a limit property.
Hence the definition of the second IRestriction interface can be ILimitRestriction or whatever name suits your business needs.
Hence ILimitRestriction can inherit from IRestriction which would mark classes inheriting ILimitRestriction still objects of IRestriction
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestrictionWithLimit<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestrictionWithLimit<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestrictionWithLimit<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}

Can you use the C# new keyword to expand properties on an interface?

I understand how the "new" keyword can hide methods in a derived class. However, what implications does it have for classes that implement interfaces that use the keyword?
Consider this example, where I decide to expand an interface by making its properties read/write.
public interface IReadOnly {
string Id {
get;
}
}
public interface ICanReadAndWrite : IReadOnly {
new string Id {
get;
set;
}
}
Then you are able to do things like this:
public IReadOnly SomeMethod() {
// return an instance of ICanReadAndWrite
}
Is this bad design? Will it cause issues for my classes that implement ICanReadAndWrite?
Edit: Here is a contrived example of why I might want to do something like this:
Say I have a factory class that returns an IShoppingCartItemReadWrite. I can then have a service layer that manipulates prices on it, changes stuff, etc. Then, I can pass these objects as IShoppingCartItemReadOnly to some kind of presentation layer that won't change them. (Yes, I know it technically can change them-- this is a design question, not security, etc.)
It's not a particularly bad idea. You should be aware that the implementor can (if it implicitly implements the interface, then a single read/write property could satisfy both interfaces) provide two distinct implementations:
class Test : ICanReadAndWrite {
public string Id {
get { return "100"; }
set { }
}
string IReadOnly.Id {
get { return "10"; }
}
}
Test t = new Test();
Console.WriteLine(t.Id); // prints 100
Console.WriteLine(((IReadOnly)t).Id); // prints 10
By the way, in general, the new inheritance modifier does nothing except to tell the compiler to shut up and don't throw out a "you're hiding that member" warning. Omitting it will have no effect in the compiled code.
You should not implement the ICanReadWrite based on IReadOnly, but instead make them separate.
ie. like this:
public interface IReadOnly
{
string Id
{
get;
}
}
public interface ICanReadAndWrite
{
string Id
{
get;
set;
}
}
Here's a class using them:
public class SomeObject : IReadOnly, ICanReadWrite
{
public string Id
{
get;
set;
}
}
Note that the same property in the class can support both interfaces.
Note that as per the comment, the only way to get a robust solution would be to also have a wrapper object.
In other words, this is not good:
public class SomeObject : IReadOnly, ICanReadWrite
{
public string Id
{
get;
set;
}
public IReadOnly AsReadOnly()
{
return this;
}
}
as the caller can just do this:
ICanReadWrite rw = obj.AsReadOnly() as ICanReadWrite;
rw.Id = "123";
To get a robust solution, you need a wrapper object, like this:
public class SomeObject : IReadOnly, ICanReadWrite
{
public string Id
{
get;
set;
}
public IReadOnly AsReadOnly()
{
return new ReadOnly(this);
}
}
public class ReadOnly : IReadOnly
{
private IReadOnly _WrappedObject;
public ReadOnly(IReadOnly wrappedObject)
{
_WrappedObject = wrappedObject;
}
public string Id
{
get { return _WrappedObject.Id; }
}
}
This will work, and be robust, right up until the point where the caller uses reflection.
This is perfectly legal and the implications for your class that implements the ICanReadAndWrite interface would simply be that when it is treated as an IReadOnly it can only read, but when treated as ICanReadAndWrite it would be able to do both.
I'm not sure if that compiles or not, but is not an advisable pattern to follow. With the ability to do explicit interface implementation, you could theoretically provide two entirely different implementations for the IReadOnly and ICanReadAndWrite versiond of the Id property. Consider altering the ICanReadAndWrite interface by adding a setter method for the property rather than replacing the property.
You can do it but I am not sure what you hope to accomplish by doing it.
public IReadOnly SomeMethod() {
// return an instance of ICanReadAndWrite
}
This method will return a reference to an IReadOnly which means that it doesn't matter that you have returned an ICanReadAndWrite. Wouldn't this approach be better?
public interface IReadOnly
{
String GetId();
}
public interface ICanReadAndWrite : IReadOnly
{
String SetId();
}

Categories