I'd like to create various sorting classes (QuickSort, MergeSort, BucketSort...etc).
I have a common Interface (ISort).
This interface has a method:
Collection<T> Sort(Collection<T> list);
Now when im trying to use a class it seems like i have to declare like this:
ISort<char> sort = new QuickSort();
The QuickSort implementation looks like this:
public class QuickSort : ISort<char>
{
public Collection<char> Sort(Collection<char> list)
{
// TODO: implement this.
return null;
}
}
This implementation is what i dont like because the T template is a char.
How can i keep this class generic so that i can use this class to sort an int, float, double, char...etc?
Just like this:
public class QuickSort<T> : ISort<T>
{
public Collection<T> Sort(Collection<T> list)
{
// TODO: implement this.
return null;
}
}
with
ISort<char> sort = new QuickSort<char>();
Sorting has nothing to do with the data type in the collection being sorted so you shouldn't force a type parameter at the class level. Also you will need to compare objects so they should implement IComparable.
You could design the interface like this and avoid tying the instance of the sorting class to the type it will sort:
interface ISort
{
ICollection<T> Sort<T>(ICollection<T> collection) where T : IComparable<T>;
}
class QuickSort : ISort
{
public ICollection<T> Sort<T>(ICollection<T> collection) where T : IComparable<T>
{
Comparer<T> comparer = Comparer<T>.Default;
// TODO: Implement
return collection;
}
}
Then you can use the same sorting object for all data types. The one drawback to this design, is that you won't be able to store state that is specific based on the generic type parameter. So QuickSort couldn't contain fields that use the generic type paremeter T.
Related
So I'm rolling my own max heap and I'm doing something wrong with using a generic class extending an interface. Say I have a class like this:
class SuffixOverlap:IComparable<SuffixOverlap>
{
//other code for the class
public int CompareTo(SuffixOverlap other)
{
return SomeProperty.CompareTo(other.SomeProperty);
}
}
And then I create my heap class:
class LiteHeap<T> where T:IComparable
{
T[] HeapArray;
int HeapSize = 0;
public LiteHeap(List<T> vals)
{
HeapArray = new T[vals.Count()];
foreach(var val in vals)
{
insert(val);
}
}
//the usual max heap methods
}
But when I try to do this:
LiteHeap<SuffixOverlap> olHeap = new LiteHeap<SuffixOverlap>(listOfSuffixOverlaps);
I get the error:
The type SuffixOverlap cannot be used as a type parameter T in the generic type or method LiteHeap<T>. There is no implicit reference conversion from SuffixOverlap to System.IComparable.
How do I create LiteHeap as a class that uses generic class T implementing IComparable so I can write new LiteHeap<SomeClass> and it will work where SomeClass implements IComparable
IComparable and IComparable<T> are different, completely-unrelated interfaces.
You need to change that to where T : IComparable<T>, so that it actually matches your class.
I have an app written in C#. My app has a class that looks like the following:
public class FinderA
{
public IEnumerable<FinderA> GetItems()
{
return FinderA.FindAll();
}
}
I want to require other classes to do something similar. I cannot use a base class because my actual implementation is already using a base class. For that reason, I want to create an interface. Currently, I'm trying the following:
public interface IFinder
{
IEnumerable<T> GetItems();
}
When I use this approach, I get a compile-time error that says: "The type or namespace name 'T' could not be found (are you missing...". To overcome this, I add <T> to the end of the interface name so it looks like this:
public interface IFinder<T>
{
IEnumerable<T> GetItems();
}
This is turn generates another compile-time error that says: "Using the generic type 'IFinder' requires 1 type arguments.". My challenge is, I want the interface to be generic. I do not want to pass in a type. Is there a way around this? If so, what/how?
There is no way around this; you'll need to actually supply the generic type argument when declaring that a class implements the interface.
You can do this at the method level instead of as a generic type on the interface itself.
public interface IFinder
{
IEnumerable<T> GetItems<T>();
}
Your code can then call it like such:
IFinder finder = // Create finder instance
IEnumerable<MyClass> discoveredClasses = finder.GetItems<MyClass>();
If you want to ensure that MyClass is a class that implements IFinder, you can constrain the method.
public interface IFinder
{
IEnumerable<T> GetItems<T>() where T : IFinder;
}
That will cause the following to generate a compiler error:
public class Foo
{
}
public class Bar
{
Bar()
{
IFinder finder = // Create finder.
// This fails because <T> (Foo) does not implement IFinder.
IEnumerable<Foo> fooItems = finder.GetItems<Foo>();
}
}
but it will allow the following to compile
public class MyFinderA : IFinder
{
IEnumerable<T> GetItems<T>() where T : IFinder
{
return // Create collection of T
}
public class Bar
{
Bar()
{
IFinder finder = // Create finder.
// This works as <T> (MyFinderA) is an IFinder implementation
IEnumerable<MyFinderA> finderItems = finder.GetItems<MyFinderA>();
}
}
If you want your interface to be generic but you are not willing to supply a type argument, you can return an IEnumerable<object>.
public interface IFinder {
IEnumerable<object> GetItems();
}
All class types extend from System.Object so that should suffice for any type in your applicacion (enums and structs would get boxed)
Please note that this approach requires the interface's consumer to cast the generic object instances to the appropiate types.
The alternate (and recommended) approach is to make the interface use type parameters, but for that you must supply the appropiate type arguments
I've tried to develop a generic class "MinHeap(T)" implementing IComparable. It works fine when generic is "int" or another class "Code". Going further and using for T a generic class "Node(Code)"
leads to the error mentioned below.
I'm probably too new and not understanding subtle differences between IComparable and IComparable(T). Does someone have an idea ?
Thanks in advance for your help,
LJ
public class MinHeap<T> where T : IComparable
{
...
}
public class Node<T> where T : IComparable
{
T data
...
public int CompareTo(object obj)
{
Node<T> otherNode = obj as Node<T>;
return this.data.CompareTo(otherNode.data);
}
...
}
public class Code : IComparable
{
public int freq;
...
public int CompareTo(object obj)
{
Code otherCode = obj as Code;
return this.freq.CompareTo(otherCode.freq);
}
}
static void Main(string[] args)
{
MinHeap<int> hInt = new MaxHeap<int>(heapSeed); // works fine
MinHeap<Code> hCode = new MinHeap<Code>(codeList); // works fine
...
Node<Code>[] nodeCodeList = new Node<Code>[freqList.Length]; // ok
MinHeap<Node<Code>> h = new MinHeap<Node<Code>>(nodeCodeList); // Error
...
}
Error message:
Error 2 The type 'Algorithms.Node(Algorithms.Code)' cannot be used as type parameter 'T' in the generic type or method 'Algorithms.MinHeap(T)'. There is no implicit reference conversion from 'Algorithms.Node(Algorithms.Code)' to 'System.IComparable'.
The class Node<T> does not implement IComparable. It just haves a constraint for the type of T.
It looks like you've tried to implement the decorator pattern. Implement the interface as well and then map the methods to the decorated object.
You're probably better off defining your generic class so that it doesn't require the type to implement IComparable<T>. That's how the .NET generic classes are implemented. They will use the default comparison for the type, or use the IComparer<T> that you pass in. For example, SortedList has these constructors (among others):
SortedList<TKey, TValue>(); // uses default comparer for TKey
SortedList<TKey, TValue>(IComparer<T> comparer); // uses supplied comparer
It's easy enough to implement:
public class MinHeap<T>
{
private IComparer<T> _comparer;
public MinHeap<T>(IComparer<T> comp)
{
_comparer = comp;
}
public MinHeap<T>()
: this(Comparer<T>.Default)
{
}
}
That way, your clients can use MinHeap<T> to hold instances of classes that do not implement IComparable<T>.
When you do your comparisons, you call _comparer.Compare(item1, item2)
On another note, there's no particular need for your heap to require a node. You can implement a binary heap in an array. See, for example, A Generic BinaryHeap Class.
You should implement IComparable interface within Node class, like this:
public class Node<T>: IComparable<Node<T>> // <- IComparable<Node<T>> implemented
where T: IComparable {
T data;
...
#region IComparable<Node<T>> Members
// interface implementation, not just a method
public int CompareTo(Node<T> other) {
// Let us be accurate with possible nulls:
if (Object.ReferenceEquals(null, other))
return 1; // <- or -1 if you think it's right
else if (Object.ReferenceEquals(data, other.data))
return 0;
else if (Object.ReferenceEquals(null, data))
return -1; // <- or 1 if you think it's right
return data.CompareTo(other.data);
}
#endregion IComparable<Node<T>> Members
}
depending on algorithm of min heap, you may have to implement IComparable> in MinHeap class as well
Let's say i have list of Tanks,Airplanes and many other things that the to common thing they implement is IHaveLocation which is and abstract class and IHaveColor which is an interface.
I want to make a list of them because i need to query the list on the basis of this two interfaces.
How do i do it ?
I can make a list of objects and then write (obj as IHaveLocation) and use his methods, and (obj as IHaveColor) and use his methods. but this is very very ugly !
I can make a list of IhaveLocation and then i need to do only one as (obj as IHaveColor). But it's also terrible
I can create a new abstract class then inherits from both, but i'm trying to avoid it.
is there some trick to this ?
I Want to make something like List<IHaveLocation and IHaveColor>
You can wrap this in a generic class with constraints on both types:
public class YourClass<T> where T : IHaveLocation, IHaveColor
{
List<T> items = new List<T>;
public void Add(T item)
{
items.Add(item);
}
// ...
}
Methods within this class can then use both interfaces as needed, as the type is guaranteed to implement them.
As I mentioned in the comments of Reed's answer, you could use generic methods to allow you to add both Tank's and Airplane's. Something like this:
class TwoTypesList<T1, T2>
{
List<Tuple<T1, T2>> m_list = new List<Tuple<T1,T2>>();
public void Add<ConcreteT>(ConcreteT item) where ConcreteT : T1, T2
{
m_list.Add(Tuple.Create<T1, T2>(item, item));
}
}
Then the usage would be:
TwoTypesList<IHaveColor, IHaveLocation> list = new TwoTypesList<IHaveColor, IHaveLocation>();
Airplane a = new Airplane();
Tank t = new Tank();
list.Add(a);
list.Add(t);
The downside, of course, is that you're storing the object twice. If you don't like that, then of course you could change the internal storage of the list to be an object or only one of the interfaces.
you can try something like :
public class YourClass<T> where T : Ihavelocation, ihavecolor{
List<T> items = new List<T>;
public void Add(T item){
items.Add(item);
}
}
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)