Heirarchical nested generic interfaces - c#

I have a chain of hierarchically nested generic interfaces, which for examples sake look like this:
ICar<TWheels, TBolts>
where TWheels : IWheels<TBolts>
where TBolts : IBolts
{
IEnumerable<TWheels> Wheels { get; set; }
}
IWheels<TBolts>
where TBolts : IBolts
{
IEnumerable<TBolts> Wheels { get; set; }
}
IBolts
{
}
Is this a sensible way of handling these generic interfaces?
It makes defining methods look like this:
public TCar GetCar<TWheels, TBolts>(int id)
where TCar : ICar<TWheels, TBolts>
where TWheels : IWheels<TBolts>
where TBolts : IBolts
{
...
}
Is there any way to reduce this code signature?

Generics in C# should be used very carefully to avoid problems like you've faced.
I'd recommend to revise interfaces hierarchy and throw generics away:
interface ICar
{
IEnumerable<IWheel> Wheels { get; set; }
}
interface IWheel
{
IEnumerable<IBolt> Bolts { get; set; }
}
interface IBolt
{
}
Then it would be great to look at use-cases, where those interfaces participate.
May be, there will be very rare cases, when you'll need IR16Wheel instead of IWheel, and type casting will be enough.
May be, it will be enough to pair non-generic interfaces with generic ones:
interface IWheel<TBolt> : IWheel
where TBolt : IBolt
{
IEnumerable<TBolt> Bolts { get; set; }
}
and use non-generics with methods like this:
public ICar GetCar(int id) { }
but also use generics in more specific cases.

Related

Is this a valid use of the new keyword in my interface? [duplicate]

Is it advisable to use the "new" keyword in a derived interface to provide a more-derived return value for a property or method having the same name?
Say I have an interface IDocument:
public interface IDocument
{
IParagraphs Paragraphs { get; }
IRevisions Revisions { get; }
IStyles Styles { get; }
}
And a derived one IRtfDocument.
public interface IRtfDocument: IDocument
{
string Rtf { get; }
...
}
I also have more-derived interfaces for IParagraphs, IRevisions and IStyles: IRtfParagraphs, IRtfRevisions, IRtfStyles. A number of RTF-specific needs drove their creation.
When I access the paragraphs of an RTF document, I'd like to avoid casting them to IRtfParagraphs. Same for revisions and styles. It would also be nice to avoid having both "IRtfParagraphs" and "IParagraphs". So what I'd like to do is this:
public interface IRtfDocument : IDocument
{
new IRtfParagraphs Paragraphs { get; }
new IRtfRevisions Revisions { get; }
new IRtfStyles Styles { get; }
string Rtf { get; }
}
Is this considered good practice? It seems to fit in this situation, but I wanted to run it by you C# veterans.
Update: So I actually went ahead and tried using "new" as described in my interfaces. My RtfDocument class ended up needing both an IDocument.Styles property and an IRtfDocument.Styles property. While I could just have the IDocument.Styles property return the value of IRtfDocument.Styles, that doesn't feel quite right as I'm implementing two properties.
It seems the compiler doesn't account for the fact that IRtfStyles derives from IStyles, so it insists I have both. It would be nice if the Liskov Substitution Principle let me just implement IRtfDocument.Styles in the RtfDocument class.
The easier solution would probably just be to have a generic interface:
public interface IFooBox<T>
where T : IFoo
{
T Foo { get; }
}
You can then have an IFooBox<IFoo> for your basic objects, or an IFooBox<IEnhancedFoo> for the enhanced version.
This type of definition will force implementers of IEnhancedFooBox to explicitly implement IFoo.Foo separately from the implementation of IEnhancedFooBox.Foo. Since this work gets tedious, I tend to reserve this for cases where a generic interface extends a non-generic interface.
For example, consider the following interfaces.
interface IFutureValue {
object Result { get; }
}
interface IFutureValue<T> : IFutureValue {
new T Result { get; }
}
It is possible to implement a general handler for all "future values" by working with IFutureValue, where code working with future values of a specific type can work with IFutureValue<T>.
To answer the question,
Is this considered good practice?
The use of new is frowned upon, in general. However, as with all frowning in programming, it is a matter of judgement. If you have found a use for new that makes sense in your context, and you've ruled out other avenues like #Servy's example, then rock the new. Be prepared to defend your decision though.
There is big potential problem with your use of the new modifier. Suppose we use your interfaces:
public interface IFoo
{
string Name { get; set; }
}
public interface IEnhancedFoo : IFoo
{
int BarCount { get; set; }
}
public interface IFooBox
{
IFoo Foo { get; set; }
}
public interface IEnhancedFooBox : IFooBox
{
new IEnhancedFoo Foo { get; set; }
}
Build out our classes:
public class EnhancedFooBox : IEnhancedFooBox
{
public IEnhancedFoo Foo { get; set; }
IFoo IFooBox.Foo { get; set; }
}
public class FooBase : IFoo
{
public string Name { get; set; }
}
public class EnhancedFoo : IEnhancedFoo
{
public int BarCount { get; set; }
public string Name { get; set; }
}
Build some methods that take interfaces...
static void Test1(IFooBox myBlah)
{
myBlah.Foo = new FooBase();
myBlah.Foo.Name = "FooBase";
}
static void Test2(IEnhancedFooBox myBlah)
{
myBlah.Foo = new EnhancedFoo();
myBlah.Foo.Name = "EnhancedFoo";
}
And then use this logic:
static void Main(string[] args)
{
var myBlah = new EnhancedFooBox();
Test2(myBlah); //first assign name to EnhancedFoo
Test1(myBlah); //second assign name to FooBase
Console.Write(myBlah.Foo.Name);
Console.ReadKey();
}
What is the expected output? Should it be FooBase or EnhancedFoo?
EnhancedFoo
Programmers unaware the property has been modified to new, will not get the expected output. This is solved using generics.

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.

What should you do if you have an interface with a collection of objects and you want both a read-only and a read-write version of the interface?

I'm currently creating some interfaces for user controls that will contain collections of objects. I want to have an interface for a control that can have objects added from the outside, and another interface for one that cannot have objects added from the outside. So far I basically have the following (simplified for this question; if it would help you to see the actual code I have thus far please let me know):
public interface IReadableFoo
{
IReadOnlyCollection<Foo> Foos { get; }
}
public interface IReadWriteFoo : IReadOnlyFoo
{
new ICollection<Foo> Foos { get; }
}
What is considered the "best practice" to do in this situation where you have an interface with a collection of objects, and you want to have both a read-only version and a read-write version? Is it considered acceptable to have an ICollection<Foo> shadowing an IReadOnlyCollection<Foo> like that?
Is there some other pattern I should be using instead? Should IReadOnlyFoo and IReadWriteFoo both inherit from a common base interface IFoo?
Edit: To clarify what I am trying to do, I'm adding the actual code that I'm working with here:
public interface IOptionSelector<T>
{
IReadOnlyCollection<T> Options { get; }
T SelectedOption { get; }
event EventHandler SelectedOptionChanged;
}
public interface IWriteableOptionSelector<T> : IOptionSelector<T>
{
new ICollection<T> Options { get; }
new T SelectedOption { get; set; }
}
Here is what you should do:
public interface IOptionSelector<T>
{
event EventHandler SelectedOptionChanged;
}
public interface IReadOnlyOptionSelector<T> : IOptionSelector<T>
{
IReadOnlyCollection<T> Options { get; }
}
public interface IWritableOptionsSelector<T> : IOptionSelector<T>
{
ICollection<T> Options { get; }
}
ReadOnly and Writeable are two separate concerns. When you have to use the new keyword on methods that you wrote that is a clear indication that you are dealing with separate concerns and need to rethink your design.

Entity Framework 6: Using interface as navigation properties possible?

is there any way to use interfaces as navigation properties in EF6?
I've found related topics for EF4 or earlier where it didn't seem to be possible; generally, inheritance seems to have improved a lot since then, but I haven't found a way to make this specific problem work yet.
Example:
public interface IPerson
{
string name { get; set; }
}
public class Man : IPerson { /* ... */ }
public class Woman : IPerson { /* ... */ }
public interface ICar
{
IPerson driver { get; set; }
}
public class Car : ICar
{
public virtual IPerson driver { get; set; } // This won't map
}
Is this possible in any way? If not, what'd be an advisable way to do this?
Because currently I don't see any way for an interface to have a set-able property whose type is some other interface (the IPerson property of ICar, for example), which kind of strikes me as a very serious design limitation?!
Okay, for those possibly facing the same issue in the future. After more testing around, this is how I'm doing it now.
public interface IPerson
{
string name { get; set; }
}
public abstract class APerson : IPerson
{
public string name { get; set; }
}
public class Man : APerson { /* ... */ }
public class Woman : APerson { /* ... */ }
public interface ICar
{
IPerson driver { get; set; }
}
public class Car : ICar
{
// This maps to the database
public virtual APerson driver { get; set; }
// And this implements the interface
ICar.driver
{
get
{
return (IPerson)driver;
}
set
{
if(!(value is APerson))
throw new InvalidCastException("driver must inherit from APerson");
driver = (APerson)value;
}
}
}
This gets a bit more tricky when having one-to-many / many-to-many relations, for that case I've written a class that inherits from Collection<Interface type>, but also implements ICollection<Abstract base type>, and again throws an exception when someone tries adding/setting any object that doesn't inherit from the abstract base class. It's basically a Collection<IPerson> that's guaranteed to only contain objects inheriting that inherit APerson, if you will.
This solution is definitely not ideal, because it just throws an exception if somebody tries assigning a value to driver that does not inherit from APerson, so no compile-time safety here.
But it's the best solution I could think of so far, if you really want to keep your interfaces separate and self-contained.

Forcing interface implementations to implement hierarchy in c#

I m writing interfaces for new project and would like to get some advice.
I have a class that have a subclass and it has a subclass. The tree of this classes is like this:
Class Car
{
Wheels Wheel;
}
Class Wheels
{
Rims Rim;
}
So to simplify: one car has one wheel and one wheel has one rim. (cant make up other better example, sorry).
So I would like to force this hierarchy in my interface implementation of ICar, IWheels and IRims.
So i did something like this (in C#):
ICar
{
IWheels Wheel;
}
IWheels
{
IRims Rim;
}
And i have a error that I can not have fields in interface implementation. So this started me thing that maybe it's wrong interface design. I would like to force interface implementations to implement this kind of hierarchy. But maybe accorting to design patterns and best practices it should be done in other way?
Could you please tell me how to design my system so that objects will be forced to implement this kind of hierarchy?
Maybe there is something not precise in my question or I missing some important info. If yes, please ask in comments.
In your interface, you'll have to make it clear that Wheels should be a property of ICar, since you cannot declare which fields an interface implementation should have. (Fields are inner workings, so the interface should not know about it).
interface ICar
{
IWheels Wheels
{
get;
}
}
You can't specify a field in an interface (and you shouldn't be able to - that's an implementation decision) but you can specify a property:
public interface ICar
{
IWheels Wheel { get; set; }
}
public interface IWheels
{
IRims Rim { get; set; }
}
You may well want to only put the getter in the interface though - it's slightly unusual to include a setter in an interface:
public interface ICar
{
IWheels Wheel { get; }
}
public interface IWheels
{
IRims Rim { get; }
}
(There are oddities if you want to override an existing (or abstract) property which only has a getter to add a setter, but it's okay to implement a "getter-only" interface with setters as well, I believe.)
You can't declare fields, but you can declare properties. That will have the same end effect of forcing a particular class to provide an instance of another class.
ICar
{
IWheels Wheel { get; set; }
}
IWheels
{
IRims Rim { get; set; }
}
As the error says, you can't specify fields in your interfaces. You can specify properties though:
interface ICar
{
IWheels Wheel { get; set; }
}
interface IWheels
{
IRims Rim { get; set; }
}
I'm not so much used to C# but it sounds to me that you can force that implementation by making Abstract classes, with the fields you want to use.
So if you extend those abstract classes you will have the fields in them available.
You'll have to make an abstract class AND an interface though...
Here it is a fully functional code...
Hope it helps...
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication10
{
//Interfaces
public interface ICar
{
string name { get;}
IWheel wheel { get;}
}
public interface IWheel
{
string brand { get;}
}
//Implementations
public class Michelin : IWheel
{
#region IWheel Members
public string brand
{
get { return "michelin"; }
}
#endregion
}
public class Toyota : ICar
{
Michelin m = new Michelin();
#region ICar Members
public string name
{
get { return "toyota"; }
}
public IWheel wheel
{
get { return m; }
}
#endregion
}
//A user of the interfaces. Only cares about ICar but knows implicitly about IWheel
public class Stand
{
public Stand()
{
cars = new List<ICar>(2);
cars.Add(new Toyota());
cars.Add(new Toyota());
}
List<ICar> cars;
public string ShowCars()
{
StringBuilder str = new StringBuilder();
foreach (ICar iterCar in cars)
{
str.AppendLine(string.Format("car {0} with wheel {1}",
iterCar.name, iterCar.wheel.brand));
}
return str.ToString();
}
}
//entry point. creates a stand and shows the cars, testing that properties are visible
class Program
{
static void Main(string[] args)
{
Stand myLittleStand = new Stand();
Console.WriteLine(myLittleStand.ShowCars());
}
}
}

Categories