Is it possible to explicitly implement base interfaces more than once? - c#

If we have two interfaces with a common base that a class must implement, is it possible to explicitly implement the common base?
Consider IEnumerable<T> for example:
public class MyMultiEnumerable: IEnumerable<int>, IEnumerable<double>
{
private readonly List<int> intList = new List<int>();
private readonly List<double> doubleList = new List<double>();
IEnumerator<double> IEnumerable<double>.GetEnumerator()
{
return doubleList.GetEnumerator();
}
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
return intList.GetEnumerator();
}
public IEnumerator GetEnumerator()
{
/*
* How do we deal with this common case, where in context it means
* two different things?
*/
throw new System.NotImplementedException();
}
}
I have no requirement to do so, but I am interested from a theoretical perspective.
Update #1
I think my use of IEnumerable and basic types is conflating this, and after thinking about it some more, I believe it could be stripped back to this problem:
public interface CommonBase
{
void CommonMethod();
}
public interface AltBase1 : CommonBase
{
void UnommonMethod();
}
public interface AltBase2 : CommonBase
{
void UnommonMethod();
}
public class Example : AltBase1, AltBase2
{
public void CommonMethod()
{
/*
* If this method needs to know whether it is being called on behalf
* of AltBase1 or AltBase2, how could it determine the implementation?
*/
}
void AltBase2.UnommonMethod()
{
}
void AltBase1.UnommonMethod()
{
}
}
Because it doesn't appear possible to explicitly implement an interface's inherited members (Example of how this might look below). I strongly believe this isn't possible via any conventional means, as it appears to be a multiple inheritance problem.
void AltBase1.CommonBase.CommonMethod()
{
// AltBase1 targeted Implementation
}
Could it be achieved via any Meta-based approach, or not at all?

I'm not sure if it's possible, but I think it's a code smell. The only scenario where this is viable is as you've phrased it - when implementing a specific version for a generic class. In that scenario, you should be leveraging the type variables, rather than how you've got it right now.

So you can get it to a point where you can compile your code. From the IEnumerable interface you have to implement GetEnumerator(), but you have to decide if you want to return intList or doubleList. Both IEnumerable<int> and IEnumerable<double> have the same signature on GetEnumerator() so there's no way to implement them both since the compiler will complain.
Take a look at this post as it has good compatible/incompatible examples of how to deal with interfaces with the same method.
Implementing two interfaces in a class with same method. Which interface method is overridden?

Related

What is the reason behind C# allowing the overloading of interface properties? [duplicate]

So, what exactly is a good use case for implementing an interface explicitly?
Is it only so that people using the class don't have to look at all those methods/properties in intellisense?
If you implement two interfaces, both with the same method and different implementations, then you have to implement explicitly.
public interface IDoItFast
{
void Go();
}
public interface IDoItSlow
{
void Go();
}
public class JustDoIt : IDoItFast, IDoItSlow
{
void IDoItFast.Go()
{
}
void IDoItSlow.Go()
{
}
}
It's useful to hide the non-preferred member. For instance, if you implement both IComparable<T> and IComparable it is usually nicer to hide the IComparable overload to not give people the impression that you can compare objects of different types. Similarly, some interfaces are not CLS-compliant, like IConvertible, so if you don't explicitly implement the interface, end users of languages that require CLS compliance cannot use your object. (Which would be very disastrous if the BCL implementers did not hide the IConvertible members of the primitives :))
Another interesting note is that normally using such a construct means that struct that explicitly implement an interface can only invoke them by boxing to the interface type. You can get around this by using generic constraints::
void SomeMethod<T>(T obj) where T:IConvertible
Will not box an int when you pass one to it.
Some additional reasons to implement an interface explicitly:
backwards compatibility: In case the ICloneable interface changes, implementing method class members don't have to change their method signatures.
cleaner code: there will be a compiler error if the Clone method is removed from ICloneable, however if you implement the method implicitly you can end up with unused 'orphaned' public methods
strong typing:
To illustrate supercat's story with an example, this would be my preferred sample code, implementing ICloneable explicitly allows Clone() to be strongly typed when you call it directly as a MyObject instance member:
public class MyObject : ICloneable
{
public MyObject Clone()
{
// my cloning logic;
}
object ICloneable.Clone()
{
return this.Clone();
}
}
Another useful technique is to have a function's public implementation of a method return a value which is more specific than specified in an interface.
For example, an object can implement ICloneable, but still have its publicly-visible Clone method return its own type.
Likewise, an IAutomobileFactory might have a Manufacture method which returns an Automobile, but a FordExplorerFactory, which implements IAutomobileFactory, might have its Manufacture method return a FordExplorer (which derives from Automobile). Code which knows that it has a FordExplorerFactory could use FordExplorer-specific properties on an object returned by a FordExplorerFactory without having to typecast, while code which merely knew that it had some type of IAutomobileFactory would simply deal with its return as an Automobile.
It's also useful when you have two interfaces with the same member name and signature, but want to change the behavior of it depending how it's used. (I don't recommend writing code like this):
interface Cat
{
string Name {get;}
}
interface Dog
{
string Name{get;}
}
public class Animal : Cat, Dog
{
string Cat.Name
{
get
{
return "Cat";
}
}
string Dog.Name
{
get
{
return "Dog";
}
}
}
static void Main(string[] args)
{
Animal animal = new Animal();
Cat cat = animal; //Note the use of the same instance of Animal. All we are doing is picking which interface implementation we want to use.
Dog dog = animal;
Console.WriteLine(cat.Name); //Prints Cat
Console.WriteLine(dog.Name); //Prints Dog
}
It can keep the public interface cleaner to explicitly implement an interface, i.e. your File class might implement IDisposable explicitly and provide a public method Close() which might make more sense to a consumer than Dispose().
F# only offers explicit interface implementation so you always have to cast to the particular interface to access its functionality, which makes for a very explicit (no pun intended) use of the interface.
If you have an internal interface and you don't want to implement the members on your class publicly, you would implement them explicitly. Implicit implementations are required to be public.
Another reason for explicit implementation is for maintainability.
When a class gets "busy"--yes it happens, we don't all have the luxury of refactoring other team members' code--then having an explicit implementation makes it clear that a method is in there to satisfy an interface contract.
So it improves the code's "readability".
A different example is given by System.Collections.Immutable, in which the authors opted to use the technique to preserve a familiar API for collection types while scraping away the parts of the interface that carry no meaning for their new types.
Concretely, ImmutableList<T> implements IList<T> and thus ICollection<T> (in order to allow ImmutableList<T> to be used more easily with legacy code), yet void ICollection<T>.Add(T item) makes no sense for an ImmutableList<T>: since adding an element to an immutable list must not change the existing list, ImmutableList<T> also derives from IImmutableList<T> whose IImmutableList<T> Add(T item) can be used for immutable lists.
Thus in the case of Add, the implementations in ImmutableList<T> end up looking as follows:
public ImmutableList<T> Add(T item)
{
// Create a new list with the added item
}
IImmutableList<T> IImmutableList<T>.Add(T value) => this.Add(value);
void ICollection<T>.Add(T item) => throw new NotSupportedException();
int IList.Add(object value) => throw new NotSupportedException();
In case of explicitly defined interfaces, all methods are automatically private, you can't give access modifier public to them. Suppose:
interface Iphone{
void Money();
}
interface Ipen{
void Price();
}
class Demo : Iphone, Ipen{
void Iphone.Money(){ //it is private you can't give public
Console.WriteLine("You have no money");
}
void Ipen.Price(){ //it is private you can't give public
Console.WriteLine("You have to paid 3$");
}
}
// So you have to cast to call the method
class Program
{
static void Main(string[] args)
{
Demo d = new Demo();
Iphone i1 = (Iphone)d;
i1.Money();
((Ipen)i1).Price();
Console.ReadKey();
}
}
// You can't call methods by direct class object
This is how we can create Explicit Interface:
If we have 2 interface and both the interface have the same method and a single class inherit these 2 interfaces so when we call one interface method the compiler got confused which method to be called, so we can manage this problem using Explicit Interface.
Here is one example i have given below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace oops3
{
interface I5
{
void getdata();
}
interface I6
{
void getdata();
}
class MyClass:I5,I6
{
void I5.getdata()
{
Console.WriteLine("I5 getdata called");
}
void I6.getdata()
{
Console.WriteLine("I6 getdata called");
}
static void Main(string[] args)
{
MyClass obj = new MyClass();
((I5)obj).getdata();
Console.ReadLine();
}
}
}

Can't use more general property type in an implementation of an interface? [duplicate]

The following code:
public interface ISomeData
{
IEnumerable<string> Data { get; }
}
public class MyData : ISomeData
{
private List<string> m_MyData = new List<string>();
public List<string> Data { get { return m_MyData; } }
}
Produces the following error:
error CS0738: 'InheritanceTest.MyData'
does not implement interface member
'InheritanceTest.ISomeData.Data'.
'InheritanceTest.MyData.Data' cannot
implement
'InheritanceTest.ISomeData.Data'
because it does not have the matching
return type of
'System.Collections.Generic.IEnumerable'.
Since a List<T> implements IEnumerable<T>, one would think that my class would implement the interface. Can someone explain what the rationale is for this not compiling?
As I can see it, there are two possible solutions:
Change the interface to be more specific and require IList be implemented.
Change my class (MyData) to return IEnumerable and implement the original interface.
Now suppose I also have the following code:
public class ConsumerA
{
static void IterateOverCollection(ISomeData data)
{
foreach (string prop in data.MyData)
{
/*do stuff*/
}
}
}
public class ConsumerB
{
static void RandomAccess(MyData data)
{
data.Data[1] = "this line is invalid if MyPropList return an IEnumerable<string>";
}
}
I could change my interface to require IList to be implemented (option 1), but that limits who can implement the interface and the number of classes that can be passed into ConsumerA. Or, I could change implementation (class MyData) so that it returns an IEnumerable instead of a List (option 2), but then ConsumerB would have to be rewritten.
This seems to be a shortcoming of C# unless someone can enlighten me.
Unfortunately, the return type must match. What you are looking for is called 'return type covariance' and C# doesn't support that.
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=90909
Eric Lippert, senior developer on C# Compiler team, mentions on his blog that they don't plan to support return type covariance.
"That kind of variance is called
"return type covariance". As I
mentioned early on in this series, (a)
this series is not about that kind of
variance, and (b) we have no plans to
implement that kind of variance in C#.
"
http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx
It's worth reading Eric's articles on covariance and contravariance.
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
For what you want to do you'll probably want to implement the interface explicitly with a class (not interface) member that returns the List instead of IEnumerable...
public class MyData : ISomeData
{
private List<string> m_MyData = new List<string>();
public List<string> Data
{
get
{
return m_MyData;
}
}
#region ISomeData Members
IEnumerable<string> ISomeData.Data
{
get
{
return Data.AsEnumerable<string>();
}
}
#endregion
}
Edit: For clarification, this lets the MyData class return a List when it is being treated as an instance of MyData; while still allowing it to return an instance of IEnumerable when being treated as an instance of ISomeData.
What if you accessed your MyData object trough the ISomeData interface?
In that case, IEnumerable could be of an underlying type not assignable to a List.
IEnumerable<string> iss = null;
List<string> ss = iss; //compiler error
EDIT:
I understand what you mean from your comments.
Anyway, what I would do in your case would be:
public interface ISomeData<T> where T: IEnumerable<string>
{
T Data { get; }
}
public class MyData : ISomeData<List<string>>
{
private List<string> m_MyData = new List<string>();
public List<string> Data { get { return m_MyData; } }
}
Converting to generic Interface with appropriate constraint offers I think the best of both flexibility and readability.
The signature of the member can't be different.
You can still return the List<string> within the get method, but the signature needs to be the same as the interface.
So simply change:
public List<string> Data { get { return m_MyData; } }
to
public IEnumerable<string> Data { get { return m_MyData; } }
Regarding your other option: changing the interface to return a List. This should be avoided. It is poor encapsulation and is regarded as a code smell.
You could implement like this:
public class MyData : ISomeData
{
private List<string> m_MyData = new List<string>();
public IEnumerable<string> Data { get { return m_MyData; } }
}
Hmm, is it a shortcoming, I would say no.
In either way, I would work around it like darin's answer, or, if you explicitly want a List accessor as well, you could do it like this:
public class MyData : ISomeData
{
IEnumerable<string> ISomeData.Data
{
get
{
return _myData;
}
}
public List<string> Data
{
get
{
return (List<string>)((ISomeData)this).Data;
}
}
}
Interfaces require that the signature of the method match with the signature of the contract exactly.
Here is a simpler example that also will not compile:
interface IFoo
{
Object GetFoo();
}
class Foo : IFoo
{
public String GetFoo() { return ""; }
}
Now as for what to do about it I would let the interface dictate the implementation. If you want the contract to be IEnumerable<T> then that is what it should be in the class as well. The interface is the most important thing here as the implementation is free to be as flexible as it needs to be.
Just be certain that IEnumerable<T> is the best choice here. (This is all highly subjective as I don't know much about your domain or the purpose of these types in your application. Good luck!)
I would choose option 2:
The point to define an interface in your code is to define an contract, and so you and other people who implement your interface know what to agree on. Whether you define IEnumerable or List in your interface is really an contract issue and belong to framework design guideline. Here is a whole book to discuss this.
Personally , I would expose IEnumerable and implement MyData to IEnumerable, and you can cast it back to List in RandomAccess() method.
Why not just return a List from your interface ...
public interface ISomeData
{
List<string> Data { get; }
}
If you know your consumers are going to both iterate over it (IEnumerable) and add to it (IList) then it seems logical to simply return a List<>.
What if you changed your interface to extend IEnumerable so you can enumerate the object and edit the data via the class property.
public interface ISomeData : IEnumerable<string>
{
IEnumerable<string> Data { get; }
}
public class MyData : ISomeData
{
private List<string> m_MyData = new List<string>();
public List<string> Data { get { return m_MyData; }
public IEnumerator<string> GetEnumerator()
{
return Data;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
If you need to have a list in your interface (known number of items with random access), you should then consider changing the interface to
public interface ISomeData
{
ICollection<string> Data { get; }
}
This will give you both the extensibility and the features you need from a list.
List<T> cannot be easily subclassed, meaning that you might have trouble returning that exact type from all the classes that want to implement your interface.
ICollection<T> on the other hand, can be implemented in various ways.
I have run into similar situations and want to give a more concrete example of why this is not allowed. Generic parts of my app deal with an interface that contains properties, and provides data through that interface to another part of the application that contains concrete classes implementing these interfaces.
The goal I think is similar to yours: the conrete classes to have more functionality, and the interface provides the absolute minimum needed for the generic part of the application. It is a good practice for the Interface to expose the least amount of functionality needed, because it maximizes compatibility/reuseability. I.e. it doesn't require an implementer of the interface to implement more than is needed.
However consider if you had a setter on that property. You create an instance of your concrete class, and pass it to some generic helper that takes an ISomeData. In that helper's code, they are working with an ISomeData. Without any type of generic T where T:new() or factory pattern, they can't create new instances to go into Data that match your concrete implementation. They simply return a list that implements IEnumerable:
instanceISomeData.Data = new SomeOtherTypeImplementingIEnumerable();
If SomeOtherTypeImplementingIEnumerable doesn't inherit List, but you've implemented .Data as a List, then this is an invalid assignment. If the compiler allowed you to do this, then scenarios like this would crash at runtime because SomeOtherTypeImplementingIEnumerable can't be cast to List. However, in the context of this helper working with ISomeData, it hasn't violated the ISomeData interface in anyway, and the assignment of any type supporting IEnumerable to .Data should be valid. So your implementation, if the compiler allowed it, could break perfectly good code working with the Interface.
This is why you can't implement .Data as a derived type. You are more tightly constraining the implementation of .Data to only except List, instead of any IEnumerable. Thus while the interface says "any IEnumerable is allowed", your concrete implementation would cause pre-existing code supporting ISomeData to suddenly break when working with your implementation of the interface.
Of course you don't really run into this scenario with only a getter, but it would complicate things to allow it in get scenarios but not otherwise.
I usually go with Jake's solution or Alioto's solution, depending on how picky I am feeling at the moment.

C# Generics: cannot convert from 'concrete class' to 'interface' error

Trying to generate a generic queue of filters to be applied to an image (where in the example filter it uses OpenCVSharp.GaussianBlur, but making it generic so I can plugin any custom filter I create).
I am struggling a bit with the C# generics and intellisense is showing:
cannot convert from 'GaussianBlur' to 'IFilter
Intellisense is recommending changing the following line:
filters.Enqueue(filter);
by casting to the interface
filters.Enqueue((IFilter<IFilterParams>)filter);
however, my question is why is casting required when the concrete class implements the interface and requires it by the generics definitions or am I misunderstanding how to declare the classes using generics.
Current implementation code is as follows:
public class FilterTest
{
private FilterCollection filters = new FilterCollection();
/* ... other irrelevant code ... */
public void ApplyFilters(ref Mat buffer)
{
var filter = new GaussianBlur(new GaussianBlurParams { KernelSize = new Size(6, 6) });
filters.Enqueue((IFilter<IFilterParams>)filter);
filters.Apply(ref buffer);
}
}
.
I am extending the Queue<> class for the FilterCollection:
public class FilterCollection : Queue<IFilter<IFilterParams>>
{
public void Apply(ref Mat buffer)
{
while (Count > 0)
Dequeue().Apply(ref buffer);
}
}
and the interfaces for IFilter and IFilterParams are as follows:
public interface IFilter<T> where T : IFilterParams
{
void Apply(ref Mat buffer);
}
public interface IFilterParams { }
And then the sample filter implementation (more or less just a wrapper in this case):
public class GaussianBlurParams : IFilterParams
{
public Size KernelSize = new Size(5, 5);
public double SigmaX = default(double);
public double SigmaY = default(double);
public BorderTypes BorderType = BorderTypes.Default;
}
public class GaussianBlur : IFilter<GaussianBlurParams>
{
private GaussianBlurParams p;
public GaussianBlur(GaussianBlurParams filterParams)
{
this.p = filterParams;
}
public void Apply(ref Mat buffer)
{
Cv2.GaussianBlur(buffer, buffer, p.KernelSize, p.SigmaX, p.SigmaY, p.BorderType);
}
}
So given:
GaussianBlur implements IFilter<GaussianBlurParams>
and IFilter<T> where T : IFilterParams
and GaussianBlurParams implements IFilterParams
Is casting the only way to fix this or is there something wrong with the structure of the generic classes/interfaces as written?
There are multiple aspects to your code that get entangled here and that altogether make the design that less than optimal. At first glance this might look like an issue of covariance, but on a closer look this is not the case. The two main aspects here are generic constraints and interfaces. To understand what I mean, let's take a look at some of the benefits of these two language elements.
Generic constraints
While generics enable you to use an implementation of a pattern for multiple types in a type-safe way, there is not much you can do to directly manipulate an object of type T from within the generic class. You can not create an instance, you can not rely on instances being reference or value types (try a comparison with null to see what that means) and you can not access any other members than the ones defined in System.Object. That's why you can use generic constraints to allow code within the generic class that can do additional things with objects of type T, like creating instances (with the new() constraint) or access additional members (by constraining T to a certain type and/or one or more interfaces).
Interfaces
Interfaces provide a contractual guarantee that the implementer will have a defined set of members. This guarantee is directed to consumers of the interface, not to its implementers. That means that you don't use interfaces to force its implementer to provide some members that are not of any value to the consumer of the interface.
What this means in your case
The key to your problems is this part of your code:
public interface IFilter<T> where T : IFilterParams
{
void Apply(ref Mat buffer);
}
public interface IFilterParams { }
In particular:
You define the generic constraint where T : IFilterParams, but IFilterParams provides no members. This constraint adds no value to your design. You restrict the implementer to a certain T, but you don't gain anything from it, because you can't do anything with instances of T that you couldn't do without the constraint.
Going one step further, you don't need the interface to be generic at all. You don't even use T in the only member that the interface provides. You could do just fine without it as far as the guarantees of the interface are concerned.
Taking a look at the GaussianBlur implementation of IFilter<T>, it is clear that you use the GaussianBlurParams only in the constructor, which is not part of the interface. So you are using the constraint of the interface only to restrict the implementer to use a Params class that implements IFilterParams. That is not even a real restriction, because the implementer can use any other parameter class for its initialization. But mainly this violates the principle that the interface provides a guarantee to its consumers, not a restriction its implementers.
Putting this all together, you can simply go for...
public interface IFilter
{
void Apply(ref Mat buffer);
}
...and you have avoided all the problems you are facing.
Even if you would need T with the constraint where T : IFilterParams for another consumer of the interface (maybe there is another interface member that you have not added in your example), your FilterCollection does not need this constraint. So you can still keep a non-generic IFilter and provide another interface (that might or might not inherit from IFilter) that provides the additional capabilities.
Ok, thanks to #zzxyz's original comment along with the comments and answer that were added and then shortly after removed, lead me to research more on covariance (which I created by adding the generic IFilterParams in order to avoid covariance), and answers/comments in SO (Contravariance? Covariance? What's wrong with this generic architecture...?) helped me correct my problem and better structure the code.
Now I understand how I was trying to 'add a banana to a bowl(fruit) (fruit being the covariant as it is not just one 'type' of fruit) when I needed to be adding the banana to a bowl(bananas)'. I am understanding but quite poorly summing up one of the answers that were unfortunately deleted.
In researching, I was able to remove the covariance by creating an abstract class with its own generic type for the filterParams and removing the IFilterParams interface altogether, thus all filters must implement the base abstract class, and now no longer cause covariance.
Since I understand it now, but not well enough to explain (above) clearly, the revised code (below) may help explain better.
First, no changes to the FilterTest class were necessary (except removing the casting from the original example which was the point of the question):
public class FilterTest
{
private FilterCollection filters = new FilterCollection();
public void ApplyFilters(ref Mat buffer)
{
var filter = new GaussianBlur(new GaussianBlurParams { KernelSize = new Size(6, 6) });
filters.Enqueue(filter);
filters.Apply(ref buffer);
}
}
Next, adjusted the Queue so it was not covariant (implements one 'type' IFilter) which exposes the needed 'Apply' method.
public class FilterCollection : Queue<IFilter>
{
public void Apply(ref Mat buffer)
{
while (Count > 0)
Dequeue().Apply(ref buffer);
}
}
public interface IFilter
{
void Apply(ref Mat buffer);
}
And finally removed the IFilterParams as they are no longer relevant to the cause. Now the sample filter implementation looks like:
public class GaussianBlur : IFilter
{
private GaussianBlurParams p;
public GaussianBlur(GaussianBlurParams filterParams)
: base(filterParams)
{
}
public override void Apply(ref Mat buffer)
{
Cv2.GaussianBlur(buffer, buffer, p.KernelSize, p.SigmaX, p.SigmaY, p.BorderType);
}
}
public class GaussianBlurParams
{
public Size KernelSize = new Size(5, 5);
public double SigmaX = default(double);
public double SigmaY = default(double);
public BorderTypes BorderType = BorderTypes.Default;
}
Problem fixed, hopefully helps others!

Can I define/constrain a member as implementing two interfaces, without generics?

The following code shows what I would like to do; that is, I would like to constrain anObject, so that it can be used as a parameter to various methods with use IInterfaceOne or IInterfaceTwo, where neither inherits from the other.
public interface IInterfaceOne { }
public interface IInterfaceTwo { }
public class Implementation : IInterfaceOne, IInterfaceTwo
{
}
public interface IInterfaceOneAndTwo : IInterfaceOne, IInterfaceTwo { }
public class UsingImplementation
{
IInterfaceOneAndTwo anObject = (IInterfaceOneAndTwo)(new Implementation()); //fails because Implementation doesnt acctually implement IInterfaceOneAndTwo
}
This example fails however as IInterfaceOneAndTwo is an interface in its own right, and Implementation does not implement it.
I know if I used generics I could constrain them, but I am wondering, if there is a way to do this without generics?
Is there a way to say anObject shall implement IInterfaceOne and IInterfaceTwo, without using IInterfaceOneAndTwo?
Not the way you have it currently. Only generic constraints have that ability.
You could rewrite it to use generics:
public class UsingImplementation<T>
where T : IInterface1, IInterface2, new()
{
T anObject = new T();
void SomeMethod() {
anObject.MethodFromInterface1();
}
}
You can also have generic methods, not only generic classes
public void DoSomething<T>(T value)
where T : IInterface1, IInterface2
{
value.DoInterface1Things();
value.DoInterface2Things();
}
Or
public void DoSomething<T>()
where T : IInterface1, IInterface2, new()
{
T anObject = new T();
}
You can't do that in C# without generics but there is an alternative workaround to solve the problem without generics that was not mentioned here and might fit for you. This style is often used together with the IoC principle. You could inject the same object twice. Let me change your sample quite a bit...
public interface IInterfaceOne { void Hello(); }
public interface IInterfaceTwo { void World(); }
public class Implementation : IInterfaceOne, IInterfaceTwo
{
public void Hello() { };
public void World() { };
}
public class UsingImplementation
{
private readonly IInterfaceOne one;
private readonly IInterfaceTwo two;
public UsingImplentation(IInterfaceOne one, IInterfaceTwo two)
{
this.one = one;
this.two = two;
}
// do the stuff you want to do with an IInterfaceOne using field one
public DoSomeThingWithOne() { one.Hello(); }
// do the stuff you want to do with an IInterfaceTwo using field two
public DoSomeThingWithTwo() { two.World(); }
}
Then you could wire up the things this way:
var oneAndTwo = new Implementation();
var a = new UsingImplementation(oneAndTwo, oneAndTwo);
// operates on the first param (which is the same as the second)
a.DoSomeThingWithOne();
// operates on the second param (which is the same as the first)
a.DoSomeThingWithTwo();
Have a look for IoC principle (Inversion of Control) and Dependency Injection and you'll find more solutions similiar to this one.
This way you don't need to create an extra Interface combining InterfaceOne and InterfaceTwo, two.
"Incoming" generic class parameters and generic method parameters can combine types, but there is no facility for variables or fields to represent "composite" types. Further, in order to pass an object to a parameter of a generic type which combines multiple constraints, the object must be cast to a type which in fact implements all of those constraints. This can be difficult.
For example, suppose class Foo and Bar both implement Intf1 and Intf2. One wishes to write a function AddToList<T>(thing as T) where T:Intf1,Intf2. Such a function will perfectly happily accept objects of type Foo or Bar. Suppose, however, one wishes to use such a function to add all objects to the same list (which might be a mix of Foo, Bar, and any number of other types that also happen to implement Intf1 and Intf2) and then later pass those objects to a function whose parameter is likewise constrained to implement both Intf1 and Intf2. One could cast to Foo any object which happened to be a Foo, and cast to Bar any object which happened to be a Bar, but if other types are written which also handle Intf1 and Intf2, it would be difficult to deal with them.
It is possible to solve the problem, somewhat awkwardly, without using Reflection or other such tricks. Define an interface IActUpon<Base1, Base2> with a method ActUpon<thingType>ActUpon(thingType thing) where thingType: Base1, Base2. Implementations of such a method will be able to pass parameter thing to other methods requiring generic method parameter constrained to Base1 and Base2. The biggest difficulties with such an approach are that one must write separate code for each possible number of constraints, and that in many places where one would have used a lambda expression one will instead have to write an implementation of IActUpon....
If this is desirable then there has to be a logical connection between IInterfaceOne and IInterfaceTwo and the implementing class should implement the combined interface:
class Implementation : IInterfaceOneAndTwo { ... }
If this is not possible, because it's not (all) your code then you may have to rethink the UsingImplementation. It simply doesn't fit the available surface.

"Interface not implemented" when Returning Derived Type

The following code:
public interface ISomeData
{
IEnumerable<string> Data { get; }
}
public class MyData : ISomeData
{
private List<string> m_MyData = new List<string>();
public List<string> Data { get { return m_MyData; } }
}
Produces the following error:
error CS0738: 'InheritanceTest.MyData'
does not implement interface member
'InheritanceTest.ISomeData.Data'.
'InheritanceTest.MyData.Data' cannot
implement
'InheritanceTest.ISomeData.Data'
because it does not have the matching
return type of
'System.Collections.Generic.IEnumerable'.
Since a List<T> implements IEnumerable<T>, one would think that my class would implement the interface. Can someone explain what the rationale is for this not compiling?
As I can see it, there are two possible solutions:
Change the interface to be more specific and require IList be implemented.
Change my class (MyData) to return IEnumerable and implement the original interface.
Now suppose I also have the following code:
public class ConsumerA
{
static void IterateOverCollection(ISomeData data)
{
foreach (string prop in data.MyData)
{
/*do stuff*/
}
}
}
public class ConsumerB
{
static void RandomAccess(MyData data)
{
data.Data[1] = "this line is invalid if MyPropList return an IEnumerable<string>";
}
}
I could change my interface to require IList to be implemented (option 1), but that limits who can implement the interface and the number of classes that can be passed into ConsumerA. Or, I could change implementation (class MyData) so that it returns an IEnumerable instead of a List (option 2), but then ConsumerB would have to be rewritten.
This seems to be a shortcoming of C# unless someone can enlighten me.
Unfortunately, the return type must match. What you are looking for is called 'return type covariance' and C# doesn't support that.
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=90909
Eric Lippert, senior developer on C# Compiler team, mentions on his blog that they don't plan to support return type covariance.
"That kind of variance is called
"return type covariance". As I
mentioned early on in this series, (a)
this series is not about that kind of
variance, and (b) we have no plans to
implement that kind of variance in C#.
"
http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx
It's worth reading Eric's articles on covariance and contravariance.
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
For what you want to do you'll probably want to implement the interface explicitly with a class (not interface) member that returns the List instead of IEnumerable...
public class MyData : ISomeData
{
private List<string> m_MyData = new List<string>();
public List<string> Data
{
get
{
return m_MyData;
}
}
#region ISomeData Members
IEnumerable<string> ISomeData.Data
{
get
{
return Data.AsEnumerable<string>();
}
}
#endregion
}
Edit: For clarification, this lets the MyData class return a List when it is being treated as an instance of MyData; while still allowing it to return an instance of IEnumerable when being treated as an instance of ISomeData.
What if you accessed your MyData object trough the ISomeData interface?
In that case, IEnumerable could be of an underlying type not assignable to a List.
IEnumerable<string> iss = null;
List<string> ss = iss; //compiler error
EDIT:
I understand what you mean from your comments.
Anyway, what I would do in your case would be:
public interface ISomeData<T> where T: IEnumerable<string>
{
T Data { get; }
}
public class MyData : ISomeData<List<string>>
{
private List<string> m_MyData = new List<string>();
public List<string> Data { get { return m_MyData; } }
}
Converting to generic Interface with appropriate constraint offers I think the best of both flexibility and readability.
The signature of the member can't be different.
You can still return the List<string> within the get method, but the signature needs to be the same as the interface.
So simply change:
public List<string> Data { get { return m_MyData; } }
to
public IEnumerable<string> Data { get { return m_MyData; } }
Regarding your other option: changing the interface to return a List. This should be avoided. It is poor encapsulation and is regarded as a code smell.
You could implement like this:
public class MyData : ISomeData
{
private List<string> m_MyData = new List<string>();
public IEnumerable<string> Data { get { return m_MyData; } }
}
Hmm, is it a shortcoming, I would say no.
In either way, I would work around it like darin's answer, or, if you explicitly want a List accessor as well, you could do it like this:
public class MyData : ISomeData
{
IEnumerable<string> ISomeData.Data
{
get
{
return _myData;
}
}
public List<string> Data
{
get
{
return (List<string>)((ISomeData)this).Data;
}
}
}
Interfaces require that the signature of the method match with the signature of the contract exactly.
Here is a simpler example that also will not compile:
interface IFoo
{
Object GetFoo();
}
class Foo : IFoo
{
public String GetFoo() { return ""; }
}
Now as for what to do about it I would let the interface dictate the implementation. If you want the contract to be IEnumerable<T> then that is what it should be in the class as well. The interface is the most important thing here as the implementation is free to be as flexible as it needs to be.
Just be certain that IEnumerable<T> is the best choice here. (This is all highly subjective as I don't know much about your domain or the purpose of these types in your application. Good luck!)
I would choose option 2:
The point to define an interface in your code is to define an contract, and so you and other people who implement your interface know what to agree on. Whether you define IEnumerable or List in your interface is really an contract issue and belong to framework design guideline. Here is a whole book to discuss this.
Personally , I would expose IEnumerable and implement MyData to IEnumerable, and you can cast it back to List in RandomAccess() method.
Why not just return a List from your interface ...
public interface ISomeData
{
List<string> Data { get; }
}
If you know your consumers are going to both iterate over it (IEnumerable) and add to it (IList) then it seems logical to simply return a List<>.
What if you changed your interface to extend IEnumerable so you can enumerate the object and edit the data via the class property.
public interface ISomeData : IEnumerable<string>
{
IEnumerable<string> Data { get; }
}
public class MyData : ISomeData
{
private List<string> m_MyData = new List<string>();
public List<string> Data { get { return m_MyData; }
public IEnumerator<string> GetEnumerator()
{
return Data;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
If you need to have a list in your interface (known number of items with random access), you should then consider changing the interface to
public interface ISomeData
{
ICollection<string> Data { get; }
}
This will give you both the extensibility and the features you need from a list.
List<T> cannot be easily subclassed, meaning that you might have trouble returning that exact type from all the classes that want to implement your interface.
ICollection<T> on the other hand, can be implemented in various ways.
I have run into similar situations and want to give a more concrete example of why this is not allowed. Generic parts of my app deal with an interface that contains properties, and provides data through that interface to another part of the application that contains concrete classes implementing these interfaces.
The goal I think is similar to yours: the conrete classes to have more functionality, and the interface provides the absolute minimum needed for the generic part of the application. It is a good practice for the Interface to expose the least amount of functionality needed, because it maximizes compatibility/reuseability. I.e. it doesn't require an implementer of the interface to implement more than is needed.
However consider if you had a setter on that property. You create an instance of your concrete class, and pass it to some generic helper that takes an ISomeData. In that helper's code, they are working with an ISomeData. Without any type of generic T where T:new() or factory pattern, they can't create new instances to go into Data that match your concrete implementation. They simply return a list that implements IEnumerable:
instanceISomeData.Data = new SomeOtherTypeImplementingIEnumerable();
If SomeOtherTypeImplementingIEnumerable doesn't inherit List, but you've implemented .Data as a List, then this is an invalid assignment. If the compiler allowed you to do this, then scenarios like this would crash at runtime because SomeOtherTypeImplementingIEnumerable can't be cast to List. However, in the context of this helper working with ISomeData, it hasn't violated the ISomeData interface in anyway, and the assignment of any type supporting IEnumerable to .Data should be valid. So your implementation, if the compiler allowed it, could break perfectly good code working with the Interface.
This is why you can't implement .Data as a derived type. You are more tightly constraining the implementation of .Data to only except List, instead of any IEnumerable. Thus while the interface says "any IEnumerable is allowed", your concrete implementation would cause pre-existing code supporting ISomeData to suddenly break when working with your implementation of the interface.
Of course you don't really run into this scenario with only a getter, but it would complicate things to allow it in get scenarios but not otherwise.
I usually go with Jake's solution or Alioto's solution, depending on how picky I am feeling at the moment.

Categories