I have often wanted to create a list of objects where each object must implement a number of interfaces. For example, I'd like to do something similar to the following:
List<T> where T : IConvertible, IComparable _myList;
Another option I considered was to create a third interface that implements these two so that any object that implements these two interfaces inherently implements mine.
public interface IConvertibleAndComparable
: IConvertible, IComparable { }
List<IConvertibleAndComparable> _myList;
With this I would be able to add any object that implements both IConvertible and IComparable, including double and int, as well as my own objects. Explicitly implementing IConvertibleAndComparable is not required since it does not add any new functionality beyond the interfaces in inherits.
I understand that the first snippet is illegal and the second, while legal, does not do what I want. Is it possible to achieve what I am trying to do? If not, would either of these be a candidate for a future C# feature?
(Note: This would be legitimate application for empty interfaces.)
Edit
In a more general sense, I'd like to perform one of the following:
private MyGenericClass<T> where T : IA, IB, ... _myClass;
where I can declare all of the restrictions on T that I need, or
public interface IMyCombinedInterface : IA, IB, ... {}
private MyGenericClass<IMyCombinedInterface> _myClass;
where any type that implements IA, IB, and ... inherently (or implicitly) implements IMyCombinedInterface (only when IMyCombinedInterface doesn't explicitly declare new functionality).
You can, as a workaround, do a kind of superposition wrapper, and store it in the list. Look here for the idea.
To your example you could do:
public class Junction
{
public IConvertible Convertible { get; private set; }
public IComparable Comparable { get; private set; }
private Junction() { }
public static Junction Create<T>(T value) where T : IConvertible, IComparable
{
return new Junction
{
Convertible = value,
Comparable = value
};
}
}
And then add Junctions to your list:
var l = new List<Junction>();
l.Add(Junction.Create(1));
While working on another project, I had an idea for another workaround. While it may not quite work for the example I posted, it could work for the original intent of the question, which was to create a combination interface for IEnumerable<T> and INotifyCollectionChanged (as #DanielHilgarth pointed out). The workaround is as follows:
Create an empty interface which implements the combination of interfaces you need.
public interface INotifyingEnumerable<T> :
IEnumerable<T>,
INotifyCollectionChanged
{
}
Create a new class which inherits from a class implementing both of these and implements the new interface.
public class MyObservableCollection<T> :
ObservableCollection<T>,
INotifyingEnumerable<T>
{
}
Now you can use the interface INotifyingEnumerable<T> as the property type, which using your implementation.
The reason this doesn't quite cover the original requirements, however, is that it doesn't allow ObservableCollection<T> to be directly assigned. The feature requested in the original post would allow this.
Related
I was having trouble with list.Sort() for a list of interface references that point to different types however the question Sort a list of interface objects provided the following solution solution
interface IFoo : IComparable<IFoo>
{
int Value { get; set; }
}
class SomeFoo : IFoo
{
public int Value { get; set; }
public int CompareTo(IFoo other)
{
// implement your custom comparison here...
}
}
In my original code rather than IFoo inherting from IComparable my class was inherting from both IFoo and ICompareable i.e.
interface IFoo
{
int Value { get; set; }
}
class SomeFoo : IFoo, IComparable<IFoo>
{
public int Value { get; set; }
public int CompareTo(IFoo other)
{
// implement your custom comparison here...
}
}
class SomeBar : IFoo, IComparable<IFoo>
{
public int Value { get; set; }
public int CompareTo(IFoo other)
{
// implement your custom comparison here...
}
}
But I was getting the error Failed to compare two elements in the array. when trying to sort a list of IFoo references.
List<IFoo> iFoos = new List<IFoo>
{
new SomeFoo{Value = 1},
new SomeFoo{Value = 15},
new SomeFoo{Value = 390},
new SomeBar{Value = 2},
new SomeBar{Value = 78},
new SomeBar{Value = 134}
}
iFoos.Sort();
Can anyone explain why my original code did not work?
Your list is a list of IFoos. So from the perspective of the list (and its sort operation), it only sees that interface and does not know anything about the concrete types.
So when it tries to order two IFoos, it cannot do that because IFoo does not implement IComparable.
The problem is that just because both your types implement IComparable<Foo> separately, there is no guarantee that all IFoo elements in the list do so. So the operation is not safe.
In order to be able to sort the elements using IComparable<IFoo>, the IFoo interface needs to implement the interface itself.
Alternatively, you could also implement a IComparer<IFoo> and pass that to Sort() which then delegates to the respective actual implementation. Of course, this is not really an elegant solution and not very future proof (if you ever create a new implementation of IFoo):
class FooComparer : IComparer<IFoo>
{
public int Compare(IFoo a, IFoo b)
{
if (a is SomeFoo)
return ((SomeFoo)a).CompareTo(b);
else if (a is SomeBar)
return ((SomeBar)a).CompareTo(b);
else
throw new NotImplementedException("Comparing neither SomeFoo nor SomeBar");
}
}
Of course, if you mean IFoo to be comparable, you should have that interface implement IComparable<IFoo> directly instead of relying on subtypes to do so. IFoo is a contract, and being sortable is a fine property to require.
Nice question with a twist!
When you are sorting a type, you expect the type to implement IComparable.
In your original code you are sorting IFoo which does not implement IComparable but in the second one it does. And that has made all the difference.
But if you had a collection of List<SomeBar> it would sort because it has IComparable implemented. Ignoring that you probably would need to use an interface of List I suggest you to use your second solution.
This behaviour is described in the documentation:
This method uses the default comparer Comparer<T>.Default for type T
to determine the order of list elements. The Comparer<T>.Default
property checks whether type T implements the IComparable generic
interface and uses that implementation, if available. If not,
Comparer.Default checks whether type T implements the IComparable
interface. If type T does not implement either interface,
Comparer.Default throws an InvalidOperationException.
Since T is IFoo, your first example works when IFoo implements IComparable<IFoo> and the second fails because it does not. I suggest you create a class FooComparer : IComparer<Foo> and pass that to the other overload of Sort.
In your first example IFoo implements IComparable<IFoo> and in the second one does not. And if you use Array.Sort or any other sort routine it will cause an ArgumentException that at least one object should implement IComparable.
I saw a C# class SomeClass that was defined like
public class SomeClass : IComparable<SomeClass>, IEquatable<SomeClass>
{
// ...
}
and I'm wondering how to translate that into English. The way I understand it seems logically impossible. How can a class inherit from a parameterized version of itself? Also, is this a common design pattern?
The key is to recognize that it's not inheriting from (or implementing) a parameterized version of itself, but rather inheriting from (or implementing) another class or interface, and using itself as a generic parameter for that target type.
For example, IComparable<T> says that there will be a CompareTo() method that takes an object of type T as a parameter. So by implementing IComparable<SomeClass> you're simply guaranteeing that a method with that signature will exist on this class:
public class SomeClass : IComparable<SomeClass>
{
public int CompareTo(SomeClass other)
{
//...
}
}
And yes, this is fairly common practice. Classes often implement the generic IComparable<> and IEquatable<> interfaces to show that they can be compared with other items of the same type. It's maybe also worth mentioning that enums in Java are declared as extending Enum<> of themselves--a pattern which is not common in C#, but does appear from time to time.
Translated in "English" it means: "Boy (or girl), you'd better be type-safe when implementing those interfaces, especially IComparable. Otherwise, you'll have to perform type casting, which I guess you don't want"
See the code below. SomeClass implemented IComparable and IComparable.
See differencies between implementations of CompareTo(object) and CompareTo(SomeClass).
namespace InterfacesStuff
{
internal class Program
{
private static void Main(string[] args)
{
var someClass1 = new SomeClass {ComparedValue = 1};
var someClass2 = new SomeClass {ComparedValue = 2};
//someClassObject defined as SomeClass
//object someClassObject = new SomeClass { ComparedValue = 2 };
//someClassObject defined as anything else but SomeClass
object someClassObject = 5;
int comparisonSomeClassBySomeClass = someClass1.CompareTo(someClass2);
int comparisonSomeClassByObject = someClass1.CompareTo(someClassObject);
}
}
public class SomeClass : IComparable, IComparable<SomeClass>, IEquatable<string>, IEquatable<int>,
IEquatable<double>
{
public int ComparedValue;
public int CompareTo(object obj)
{
var presumedSomeClassObject = obj as SomeClass;
if (presumedSomeClassObject != null)
{
if (ComparedValue <= ((SomeClass) obj).ComparedValue)
return -1;
}
return 0;
}
public int CompareTo(SomeClass other)
{
if (ComparedValue <= other.ComparedValue)
return -1;
return 0;
}
public bool Equals(double other)
{
throw new NotImplementedException();
}
public bool Equals(int other)
{
throw new NotImplementedException();
}
public bool Equals(string other)
{
throw new NotImplementedException();
}
}
}
It is not Inheriting, It is implementing the IComparable Interface. what is going on is
Someclass Implements the Icomparable and the IEquatable interface. Implementing an interface is like signing a contract stating you gaurentee that this class will implement the methods on an interface.
Icomparable msdn, IEquatable. If you look at the MSDN pages you can see that SomeClass gaurentees it will implement the methods in some fashion.
This is very common practice and it is many different names. The ones I hear most are programming by contract and Implementation over Inhertience. It lets you do a lot of cool things, like Dependency Injection, Proper Unit testing, better Generics. It does this because the compiler doesnt need to know the concrete class that your object is implementing. It just needs to know that it has certain functions on it. For further reading on this I would read Chapter one of the gang of four Design pattern book.
Wikipedia link Specifically the Introduction to Chapter one section
It doesn't really have to be convenient to express it in english for it to be valid code, although I'd probably read that as "SomeClass is comparable and equatable to itself". That doesn't really explain what's going on though, it's just a way of expressing it.
In C# types can be generic over categories of other types. Generic types are basically "type constructors". They take other types as parameters, and use them to construct new types. For instance, IEnumerable<int> and IEnumerable<string> are two completely different types. The non-generic version (IEnumerable) is a third one. In C# a type A can inherit ANY other type B as long as none of the following is true (I hope I didn't miss anything):
B is already a subtype of A
B is a class and A has already inherited another class
B is a struct
A is an interface but B is not
A is the same type as B
B is sealed
A is a struct and B is not an interface
This even makes the following code legal:
class Foo<T>
{
public T Value;
}
class Foo : Foo<int>
{
}
Foo and Foo<T> are different types, so there's no problem at all for one to inherit the other.
You can read more about generics here:
https://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx
And about inheritance here:
https://msdn.microsoft.com/en-us/library/ms173149.aspx
The code you posted does not inherit from any class. It is implementing certain so-called Interfaces. How to translate that snippet: "I guarantee that SomeClass will be Comparable and equatable with other SomeClass instances. I will provide definitions in this class on how to do that."
About specializing a class from some other class...
What you can do is something like this:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Pet
{
protected string name;
public Pet(String name)
{
this.name = name;
}
}
class Dog : Pet
{
private List<String> tricks;
public Dog(String name, List<String> tricks):base(name)
{
this.tricks = tricks;
}
}
class Program
{
static void Main(string[] args)
{
List<string> tricks = new List<string>();
tricks.Add("sit");
tricks.Add("jump");
tricks.Add("bark");
Dog puppy = new Dog("Fido", tricks);
}
}
}
Dog inherits from Pet. Dog calls Pet's constructor at creation. Whatever name you pass into Dog constructor, it will forward it to Pet constructor.
Because what happens is that a subclass first calls the constructor of its superclass with the appropriate arguments. Then it runs its own constructor. Whatever is declared as public or protected in a class will be visible to its subclasses.
Therefore Dog will have name and also a list of tricks:
You achieve this kind of view with the "Locals" window.
I recommend that you read some tutorials on c# inheritance, interfaces and generics
Is there a way to define the type in a generic class like List to have contain objects which only implent multiple interfaces? Possibly class type and interfaces.
For example:
List<myObjectBase, IDisposable, IClonable> myList;
Not sure if I understood correctly, but how about this:
class MyList<T> : List<T>
where T : myObjectBase, IDisposable, IClonable
{
}
This way you can only add objects to the list which derive from the base and implement those interfaces.
No. In that case you would have to express that in the following way:
public class CommonStuff : MyObjectBase, IDisposable, IClonable {}
Then you can write:
List<CommonStuff> myList;
No, multiple generic parameters are not supported.
It wouldn't make much sense either. There would be no benefit of using the generic List<T> class over something like an ArrayList. You would lose all of the type safety benefits and you'd wind up still having to cast things all over the place.
The better option would be to create a composite class that handles all of the things you want to do...and then use that:
public class CommonBase : MyBaseClass, ICloneable, IDisposable
{
}
And then use that as your generic parameter:
var newList = new List<CommonBase>();
One approach that may be helpful is to define an interface ISelf<out T> whose one member, Self, simply returns "this" as a T; then for any interface IWhatever that might be combined, define a generic version IWhatever<out T> which inherits both the IWhatever and ISelf<T>. In that case, a class Whizbang which implements IFoo<Whizbang> and IBar<Whizbang> will implicitly implement ISelf<Whizbang>, IFoo<IBar<Whizbang>>, IBar<IFoo<Whizbang>>, etc. A routine which needs something that implements both IFoo and IBar can accept a parameter of type IFoo<IBar>; that parameter will implement IFoo; its Self property will implement IBar. Any object which implements multiple interfaces using this pattern may be cast to a nested interface type of the given form using some or all of the interfaces, listed in any order.
Below is the simplest solution for adding multiple interfaces that worked for me.
List<ICommonInterface> myList = new List<ICommonInterface>()
myFirstClass m1C = new myFirstClass();
mySecondClass m2C = new mySecondClass();
myList.Add(m1C);
myList.Add(m2C);
foreach (var item in myList)
{
item.Clone();
item.Dispose();
}
class myFirstClass : ICommonInterface
{
// implement interface methods
}
class mySecondClass : ICommonInterface
{
// implement interface methods
}
interface ICommonInterface : IDisposable, IClonable
{
}
interface IDisposable
{
void Dispose(){}
}
interface IClonable
{
void Clone(){}
}
You can use an ArrayList and can check the Type of an object in this list - maybe it is handier.
if(list[i] is Type)
Is there anyway to force a constraints for a generic definition to implement a "generic interface" ... that is, I want the class to support passing an interface and a generic class constraining it so that the class implements the interface. For example if I say:
MyGenericClass<IMyInterface, MyImplementation>.DoSomething();
That should be constrained so that MyImplementation implements IMyInterface
As far as I know that can be achieved by
public class Dynamic_Loader<T, S> where S: T
Now, is there anyway to also force T to be an interface?
Edit: The purpose of this was to have something like:
private static List<T> interfaceList = new List<T>();
public static List<T> InterfaceList {get { return interfaceList;}}
public static void Add(S input) { interfaceList.Add(input);}
and have the list restricted to only interfaces (since it is supposed to return implementations of certain interfaces)
Do you mean, can a constraint also be put on T like where T : interface?
If so, then no: this list pretty much covers your options.
What you have is as close as it gets, I believe.
Out of curiosity, what would be your reason for wanting to constrain T to be an interface?
Or do you mean can a constraint also be put on T for T to implement some specific interface?
If so, then yes: simply have two where clauses (e.g., where S : T where T : U).
where T: IMyOtherInterfaceForT
Example:
public class Test<T, V>
where T : V
where V : IEnumerable<int>
{
}
You could do something like this to enforce it at runtime instead of compile time.
public class Test<T> where T : class
{
public Test()
{
Type t = typeof( T );
if( !t.IsInterface )
throw new ArgumentException( "T must be an interface type" );
}
}
When I press f12 on the ArrayList keyword to go to metadata generated from vs2008, I found that the generated class declaration as follows
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
I know that the IList already inherits from ICollection and IEnumerable, so why does ArrayList redundantly inherit from these interfaces?
OK, I've done some research. If you create the following hierarchy:
public interface One
{
void DoIt();
}
public interface Two : One
{
void DoItMore();
}
public class Magic : Two
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
And compile it, then reference the DLL in a different solution, type Magic and Press F12, you will get the following:
public class Magic : Two, One
{
public Magic();
public void DoIt();
public void DoItMore();
}
You will see that the interface hierarchy is flattened, or the compiler is adding the interfaces in? If you use reflector you get the same results too.
Update: If you open the DLL in ILDASM, you will see it saying:
implements ...Two
implements ...One.
The extra interfaces are shown because they are implied by IList. If you implement IList, you must also implement ICollection and IEnumerable.
I am just guessing, but I think in reality it only implements IList in code, but the documentation shows the rest of the interfaces as well to make it explicit to the programmer using the class.
From MSDN....
If a class implements two interfaces
that contain a member with the same
signature, then implementing that
member on the class will cause both
interfaces to use that member as their
implementation.
Explicit implementation is also used
to resolve cases where two interfaces
each declare different members of the
same name such as a property and a
method:
Don't accept this as answer.
I am repeating what workmad3 said above.
By implementing it in ArrayList, it becomes easy for one to know - which interfaces ArrayList implements rather that going up to IList to find that it implements ICollection & IEnumerable.
That avoids the need for going back & forth the inheritance chain.
EDIT: At the basic level, an interface implementing another interface cannot provide the implementation. The class derived (from IList) hence indirectly implements ICollection & IEnumerable as well. So, even if you write your own class implementing IList (and not add ICollection, IEnumerable in the declaration) - you will see that it will have to provide the implementation for ICollection & IEnumerable.
And workmad3's reasoning makes sense.
My guess would be that the CLR does not support an interface that inherits from another interface.
C# however does support this construct but has to 'flatten' the inheritance tree to be CLR compliant.
[Edit]
After taking advise from below quickly setup a VB.Net project:
Public Interface IOne
Sub DoIt()
End Interface
Public Interface ITwo
Inherits IOne
Sub DoIt2()
End Interface
Public Class Class1
Implements ITwo
Public Sub DoIt() Implements IOne.DoIt
Throw New NotImplementedException()
End Sub
Public Sub DoIt2() Implements ITwo.DoIt2
Throw New NotImplementedException()
End Sub
End Class
Compiling results in the following (C#):
public class Class1 : ITwo
{
public Class1();
public void DoIt();
public void DoIt2();
}
This show that VB.Net does NOT flatten the interface hierarchy as opposed to C#. I have no clue as to why this would be.
ArrayList is supposed to explicitly contain ICollection and IEnumerable implementations, just like the IList interface, which contains ICollection and IEnumerable implementations. But the ArrayList implementation should not be dependent on IList. In such a way that if the list structure changes, no effect will be felt on the ArrayList behavior. So they must be considered completely independent.
Inheriting ICollection and IEnumerable is important to ensure ArrayList independence. So if the IList structure changes and does not run ICollection or IEnumerable, the ArrayList structure will not change.
For example:
If you create the following hierarchy:
public interface IOne
{
void DoIt();
}
public interface ITwo : IOne
{
void DoItMore();
}
public class Magic : ITwo
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
Now interface ITwo decides not to use IOne implementation in its implementation. Since we explicitly inherited from IOne in the implementation of Magic, the program runs independently and does not depend on changes to the ITwo interface.
public interface IOne
{
void DoIt();
}
public interface ITwo
{
void DoItMore();
}
public class Magic : ITwo,IOne
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
Update: If you look at the .NET source code and Microsoft documentation, you will see that the generated metadata is different from what you mentioned in the question.
This probably goes back to how IL emitted