Call Compare Method from another class - c#

Please help me to resolve the following problem:
First of all, I have one class
namespace ProbA
{
public class A : IComparer
{
Private int a;
public int IComparer.Compare(object CurrentNode, object DataNode)
{
WBPMember Current = (WBPMember)CurrentNode;
WBPMember Data = (WBPMember)DataNode;
return Current.a- Data.a;
}
}
}
namespace BST
{
public class BinarySearchTree<T> : ICollection<T>, IEnumerable<T>
{
public virtual void Add(T data)
{
// create a new Node instance
BinaryTreeNode<T> n = new BinaryTreeNode<T>(data);
int result;
BinaryTreeNode<T> current = root, parent = null;
while (current != null)
{
result = /**** I need to call the Class A compare method.
}
}
}
}
I want to execute ClassA Compare method, when following statement execute in ProbA assembly.
A objA = new A();
BinarySearchTree<A> bst = new BinarySearchTree<A>();
Bst.Add(objA);
Problem is both classes are in different libraries. And BinarySearchTree is generic class. So how can i compare A typed object in Add function of BinarySearchTree class.
I update this post for more clarification.
Let me describe my problem more clearly.
I have some type of businessrules. And as per different business rules , I need to construct different type of BST. Offcouse, BST generates at the same logic but on the different kind of logic of comparision.
Lets say, I have BusineesRules assembly. And it contains 4 kind of rules like Business1, Business2, Business3. Business4.
And I have an assembly for generating BST and other traversal methods. This BST is fully generic and in assembly BST
Now when I need to implement compare method in each class.
Like,.
Public Class Business1: IComparer
{
// Implemetation of Icompare.
}
Same for all the other classes.
When I try to add instance of Business1 in BST, make comparision based on its own implementation and same for other classes.
Code for BST is given below:
public class BinarySearchTree<T> : ICollection<T>, IEnumerable<T>
{
#region "Private Member Variables"
private BinaryTreeNode<T> root = null;
private int count = 0;
private IComparer<T> comparer = Comparer<T>.Default; // used to compare node values when percolating down the tree
#endregion
#region Constructors
public BinarySearchTree() { }
public BinarySearchTree(IComparer<T> comparer)
{
this.comparer = comparer;
}
#endregion
public virtual void Add(T data)
{
// create a new Node instance
BinaryTreeNode<T> n = new BinaryTreeNode<T>(data);
int result;
// now, insert n into the tree
// trace down the tree until we hit a NULL
BinaryTreeNode<T> current = root, parent = null;
while (current != null)
{
result = comparer.Compare(current.Value, data);
if (result == 0)
// they are equal - attempting to enter a duplicate - do nothing
return;
else if (result > 0)
{
// current.Value > data, must add n to current's left subtree
parent = current;
current = current.Left;
}
else if (result < 0)
{
// current.Value < data, must add n to current's right subtree
parent = current;
current = current.Right;
}
}
// We're ready to add the node!
count++;
if (parent == null)
// the tree was empty, make n the root
root = n;
else
{
result = comparer.Compare(parent.Value, data);
if (result > 0)
// parent.Value > data, therefore n must be added to the left subtree
parent.Left = n;
else
// parent.Value < data, therefore n must be added to the right subtree
parent.Right = n;
}
}
#endregion
** Add Generic comparer method.
This following class is added into businessrule classes assembly.
class BusinessRules: IComparer
{
public int Compare(object CurrentHNode, object DataNode)
{
TreeMember Current;
TreeMember Data;
if (CurrentHNode is Current)
{
Current = (TreeMember)CurrentHNode;
}
else
throw new ArgumentException("Object is not type of WBPMember");
if (DataNode is Data)
{
Data = (TreeMember)DataNode;
}
else
throw new ArgumentException("Object is not type of WBPMember");
return Current.TreeIndex - Data.TreeIndex;
}
}
You can see following line in the code.
“result = comparer.Compare(current.Value, data);”
But it is compare of binarysearch class. So I can call compare method business1 or business2.?
Is this comparor implemetation useful to compare objects in BinarySearchTree.Add() method?
One more important thing is that BST and other businessrule classes are different assemblies.

Well if you want to call Compare, your BinarySearchTree class will need to have a reference to an instance of the comparer. Assuming you want to make the binary search tree consistent, it seems logical to use the same comparer for all operations acting on a single instance of the search tree. I would suggest that:
You change your A class to implement IComparer<WBPMember> instead of just IComparer
You create a constructor in BinarySearchTree which takes an IComparer<T> and remembers it for later.
You optionally create a parameterless constructor in BinarySearchTree using the default comparer for T
Something like this:
public class BinarySearchTree<T> : ICollection<T>, IEnumerable<T>
{
private readonly IComparer<T> comparer;
public BinarySearchTree(IComparer<T> comparer)
{
// TODO: Work out how to handle comparer == null (could throw an
// exception, could use the default comparer).
this.comparer = comparer;
}
public BinarySearchTree() : this(Comparer<T>.Default)
{
}
// Now within Add, you can call comparer.Compare(current.Value, data)
}

Related

how do I create GetEnumerator of my circular list?

I have to create my own circular list, I using the generic one.
first i create the Node<D> class which represents the data and the next of the element
private class Node<D> {
public D info;
public Node<D> next;
public Node() {
}
public Node(D p) {
info = p;
}
}
To create the circular list, I create the circularList<T> class. this class using Node<> as item of the element.
Here is the CircularList<T> class
class CircularList<T> : IEnumerable<T> {
public Node<T> start;
public Node<T> rear;
public int count = 0;
public CircularList(T firstItem) {
start = new Node<T>(firstItem);
rear = start;
rear.next = start;
}
public void Insert(T newItem) {
//Inserting code here
}
public void Update(T oldItem, T newItem) {
//Updating code is here
}
public void Delete(T theItem) {
//deleting code is here
}
}
when I start to loop using foreach
foreach(string item in CircularList<string>){
}
I got an error says that the circularlist class needs GetEnumerator().
Actually I can loop all of my circular list, but I am using do-while and I need Node<T> to start the loop. but I don't want using Node and do-while.
How do I create the GetEnumerator()?
Any help appreciated. :)
Thank you
Note: I really-really don't understand about IEnumerable and those things, please go easy with the example and explanation.
You need to implement GetEnumerator() method from IEnumerable for the foreach to work.
Use something like following:
public class CircularList<T> : IEnumerable<T>
{
private List<T> mylist = new List<T>();
public T this[int index]
{
get
{
return this.mylist[index];
}
set
{
this.mylist.Insert(index, value);
}
}
public IEnumerator<T> GetEnumerator()
{
return this.mylist.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
mylist maintains the list of type T which you would insert, update and delete.
EDIT
myList is just the backing storage of your "custom" list. As long as you are implementing your underlying functionality correctly, myList could be array, arraylist and so on.
For simplicity, I've used List<T> here which already implements the interface IEnumerable<T> and IEnumerator<T>( notice IEnumera**tor** not IEnumerable).
See this answer for more details on the difference between IEnumerator and IEnumerable
Moreover, The foreach statement hides the complexity of the enumerators.
See IEnumerator for more details.
The compiler turns the foreach into something like this:
CircularList<string> testList=new CircularList<string>();
IEnumerator testEnumerator= testList.GetEnumerator();
while (testEnumerator.MoveNext())
{
string yourForEachIteratorVariable = (string)testEnumerator.Current
...
}
Please note that the codes here are only for the illustration purposes. You could/should modify to make it more flexible and "performant" according to your need/requirement.
And for linked list, you don't need a backing List<T>, you could simply add/insert on your head node and implement GetEnumerator() something like below:
public IEnumerator<T> GetEnumerator()
{
var node = start;
while(node != null)
{
yield return node.info;
node = node.next;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

How can I implement IEnumerator<T>?

This code is not compiling, and it's throwing the following error:
The type 'TestesInterfaces.MyCollection' already contains a definition for 'Current'
But when I delete the ambiguous method, it keeps giving other errors.
Can anyone help?
public class MyCollection<T> : IEnumerator<T>
{
private T[] vector = new T[1000];
private int actualIndex;
public void Add(T elemento)
{
this.vector[vector.Length] = elemento;
}
public bool MoveNext()
{
actualIndex++;
return (vector.Length > actualIndex);
}
public void Reset()
{
actualIndex = -1;
}
void IDisposable.Dispose() { }
public Object Current
{
get
{
return Current;
}
}
public T Current
{
get
{
try
{
T element = vector[actualIndex];
return element;
}
catch (IndexOutOfRangeException e)
{
throw new InvalidOperationException(e.Message);
}
}
}
}
I think you're misunderstanding IEnumerator<T>. Typically, collections implement IEnumerable<T>, not IEnumerator<T>. You can think of them like this:
When a class implements IEnumerable<T>, it is stating "I am a collection of things that can be enumerated."
When a class implements IEnumerator<T>, it is stating "I am a thing that enumerates over something."
It is rare (and probably wrong) for a collection to implement IEnumerator<T>. By doing so, you're limiting your collection to a single enumeration. If you try to loop through the collection within a segment of code that's already looping through the collection, or if you try to loop through the collection on multiple threads simultaneously, you won't be able to do it because your collection is itself storing the state of the enumeration operation. Typically, collections (implementing IEnumerable<T>) return a separate object (implementing IEnumerator<T>) and that separate object is responsible for storing the state of the enumeration operation. Therefore, you can have any number of concurrent or nested enumerations because each enumeration operation is represented by a distinct object.
Also, in order for the foreach statement to work, the object after the in keyword, must implement IEnumerable or IEnumerable<T>. It will not work if the object only implements IEnumerator or IEnumerator<T>.
I believe this is the code you're looking for:
public class MyCollection<T> : IEnumerable<T>
{
private T[] vector = new T[1000];
private int count;
public void Add(T elemento)
{
this.vector[count++] = elemento;
}
public IEnumerator<T> GetEnumerator()
{
return vector.Take(count).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
You need to define the interface the current is implementing.
Object IEnumerator.Current
{
//
}
public T Current
{
//
}
This way your class has 2 Current properties. but you can access them both.
MyCollection<string> col = new MyCollection<string>();
var ienumeratort = col.Current; //Uses IEnumerator<T>
var ienumerator = (IEnumerator)col.Current; //uses IEnumerator
I think with C# 2.0 onwards, you have a very easy way of implementing iterator and compiler does a lot of heavy lifting behind the scene by creating state machine. It's worth looking into it. Having said that, in that case your implementation would look something below:
public class MyCollection<T>
{
private T[] vector = new T[1000];
private int actualIndex;
public void Add(T elemento)
{
this.vector[vector.Length] = elemento;
}
public IEnumerable<T> CreateEnumerable()
{
for (int index = 0; index < vector.Length; index++)
{
yield return vector[(index + actualIndex)];
}
}
}
I am not sure about the purpose of actualIndex though - but i hope you get the idea.
After proper initialization of MyCollection, below is snippet somewhat looks like from consumer perspective:
MyCollection<int> mycoll = new MyCollection<int>();
foreach (var num in mycoll.CreateEnumerable())
{
Console.WriteLine(num);
}

IEnumerator<T> / IEnumerable<T> with position stored only temporarily?

I'm developing a graph where I need to keep the memory usage per node as low as possible. Each node implements IEnumerator / IEnumerable.
IEnumerator / IEnumerable make use of "position" in the canonical examples, which is a persistent cursor value required for iteration (e.g. as used by foreach).
What I need to avoid is storing this "position" value internally to the node itself, as this adds overhead where every byte counts.
How can I construct the node class such that a temporary object stores this value -- preferably on the stack -- only while an iteration is taking place, and not as part of the node itself? Is this possible?
Typically an IEnumerable<T> doesn't store a position - only an IEnumerator<T> does. (Iterator block implementations are odd in terms of implementing both, but they're definitely an anomaly.)
I suggest that you take the same approach that List<T> does: implement IEnumerable<T> with explicit interface implementation, but also have a public method returning a custom mutable struct (horrible I know, but it does solve your problem) which contains a reference to your node and the position within it. When you iterate using foreach, that struct value will only be stored on the stack (normally - assuming you're not doing this within an iterator block, for example).
The normal implementation would be to create a mutable reference type just for the IEnumerator<T>. Normally this is okay as even if you have a lot of IEnumerable<T> values live at the same time, you have few IEnumerator<T> values. Are you concerned about the concurrent number of live objects, or garbage collection?
If "node" is the underlying data, then it is very incorrect to store the position in the node, as you are meant to be able to have separate enumerators. It is unclear how you are currently implementing this API, but if you use an " iterator block " with the position as a local variable it will be done correctly, but on the heap. You can also implement an iterator manually on the stack by creating a struct iterator. It is important that the public GetEnumerator() is returned as the struct type, so you will need to use explicit interface implementation for IEnumerable etc. Note that foreach over Node directly will use the stack, but IEnumerable etc will use the heap.
For example (using a basic linked-list):
using System;
using System.Collections;
using System.Collections.Generic;
class Program
{
static void Main()
{
var list = new MyList<int>();
list.Add(1);
list.Add(2);
list.Add(3);
foreach (var i in list)
{ // this IS NOT using IEnumerable/IEnumerable<T>
Console.WriteLine(i);
}
}
}
public class MyList<T> : IEnumerable<T>
{
internal sealed class Node
{
private readonly T value;
public Node Next { get; set; }
public T Value { get { return value; } }
public Node(T value) { this.value = value; }
}
Node root;
public void Add(T value)
{
var newNode = new Node(value);
var node = root;
if (node == null) root = newNode;
else
{
while (node.Next != null) node = node.Next;
node.Next = newNode;
}
}
public Enumerator GetEnumerator() { return new Enumerator(this); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }
public struct Enumerator : IEnumerator, IEnumerator<T>
{
void IDisposable.Dispose() { node = null; list = null; }
void IEnumerator.Reset() { node = null; }
object IEnumerator.Current { get { return Current; } }
private MyList<T> list;
private Node node;
public bool MoveNext()
{
if (node == null)
{
node = list.root;
return node != null;
}
else
{
if (node.Next == null) return false;
node = node.Next;
return node != null;
}
}
internal Enumerator(MyList<T> list) { this.list = list; node = null; }
public T Current { get { return node == null ? default(T) : node.Value; } }
}
}

DRY this method

I need help making this method generic. It is repeated about ten times to get lists for different web list controls (substituting "MyType" for the type used in the particular control).
private static IList<MyType> GetList(RequestForm form)
{
// get base list
IMyTypeRepository myTypeRepository = new MyTypeRepository(new HybridSessionBuilder());
IList<MyType> myTypes = myTypeRepository.GetAll();
// create results list
IList<MyType> result = new List<MyType>();
// iterate for active + used list items
foreach (MyType myType in myTypes)
{
if (myType.Active || form.SolutionType.Contains(myType.Value))
{
result.Add(myType);
}
}
// return sorted results
result.OrderBy(o => o.DisplayOrder);
return result;
}
Let me know if this isn't enough information. I think this requires more advanced language features that I'm just getting acquainted with. Maybe I should make them all use the same repository?
Thanks for your help.
EDIT:
Thanks for your help. I don't have any peer support, so this board is fantastic and I learned something from each of you. I wish I could accept all the answers.
You could firstly make your function a bit more terse like this:
private static IList<MyType> GetList(RequestForm form)
{
// get base list
IMyTypeRepository myTypeRepository =
new MyTypeRepository(new HybridSessionBuilder());
IList<MyType> myTypes = myTypeRepository.GetAll();
return myTypes.Where(x => x.Active || form.SolutionType.Contains(x.Value))
.OrderBy(x => x.DisplayOrder).ToList();
}
At that point, most of the content of the function is directly related to MyType, so how you can further improve it depends largely on how MyType relates to the other types involved. For example, here is a hypothetical version that you could write if your other types followed a reasonable-looking (to me) contract:
private static IList<T> GetList(RequestForm form) where T : OrderedValueContainer
{
// we'll want to somehow genericize the idea of a TypeRepository that can
// produce these types; if that can't be done, we're probably better off
// passing a repository into this function rather than creating it here
var repository = new TypeRepository<T>(new HybridSessionBuilder());
IList<T> myTypes = repository.GetAll();
// the hypothetical OrderedValueContainer class/interface
// contains definitions for Active, Value, and DisplayOrder
return myTypes.Where(x => x.Active || form.SolutionType.Contains(x.Value))
.OrderBy(x => x.DisplayOrder).ToList();
}
If all the types implement the same interface, (if they don't then make them, and make sure to add all the properties to the interface that are needed in this method) then you can do something like this:
private static IList<T> GetList(RequestForm form)
where T: IMyInterface
{
// get base list
IMyTypeRepository myTypeRepository = new MyTypeRepository(new HybridSessionBuilder());
IList<T> myTypes = myTypeRepository.GetAll();
// create results list
IList<T> result = new List<T>();
// iterate for active + used list items
foreach (T myType in myTypes)
{
if (myType.Active || form.SolutionType.Contains(myType.Value))
{
result.Add(myType);
}
}
// return sorted results
return result.OrderBy(o => o.DisplayOrder).ToList();
}
One other change I made is the last line, where you had the orderby on a seperate line and were never actually capturing the Ordered list.
EDIT: To solve the repository problem, you can have a repository factory of sorts that returns the correct repository based on the type of T:
public static IMyTypeRepository GetRepository(Type t)
{
if(t == typeof(Type1))
{
return Type1Repository();
}
if(t == typeof(Type2))
{
return Type2Repository();
}
.......
}
Assuming of course that all your repositories implement the IMyRepository interface.
First of all, all your types must implement a common interface that define properties like Active, Value ...
Also, for what I can tell, there must be a repository interface for all repositories independently of the MyType so that you can use a generic method like this. The GetAll() method should be defined in the IRepository.
public interface IRepository<T> where T : IMyType
{
IList<T> GetAll();
}
public class RepositoryFactory
{
public static IRepository<T> createRepository<T>(ISessionBuilder sb) where T : IMyType
{
// create repository
}
}
public interface IMyType
{
bool Active { get; }
string Value { get; }
}
private static IList<T> GetList(RequestForm form) where T : IMyType
{
// get base list
IRepository<T> repository = RepositoryFactory.createRepository<T>(new HybridSessionBuilder());
IList<T> myTypes = repository.GetAll();
// create results list
IList<T> result = new List<T>();
// iterate for active + used list items
foreach (T myType in myTypes)
{
if (myType.Active || form.SolutionType.Contains(myType.Value))
{
result.Add(myType);
}
}
// return sorted results
return result.OrderBy(o => o.DisplayOrder).ToList();
}
Assuming that the repositories share a common interface, the issue with the repository should be easy to fix: add a static function such as
public static IRepository RepositoryForType(Type t)
{
if(t == typeof(SomeClass))
return new SomeClassRepository(new HybridSession());
else if ...
else throw new InvalidOperationException("No repository for type " + t.Name);
}
This should require you the least amount of changes to your existing code, but mind that in the future you'll have to add classes support for new repositories in this function as you add new repositories in your project (if you're using unit testing you'll easily figure out if you forgot about this helper anyway).

How to use foreach keyword on custom Objects in C#

Can someone share a simple example of using the foreach keyword with custom objects?
Given the tags, I assume you mean in .NET - and I'll choose to talk about C#, as that's what I know about.
The foreach statement (usually) uses IEnumerable and IEnumerator or their generic cousins. A statement of the form:
foreach (Foo element in source)
{
// Body
}
where source implements IEnumerable<Foo> is roughly equivalent to:
using (IEnumerator<Foo> iterator = source.GetEnumerator())
{
Foo element;
while (iterator.MoveNext())
{
element = iterator.Current;
// Body
}
}
Note that the IEnumerator<Foo> is disposed at the end, however the statement exits. This is important for iterator blocks.
To implement IEnumerable<T> or IEnumerator<T> yourself, the easiest way is to use an iterator block. Rather than write all the details here, it's probably best to just refer you to chapter 6 of C# in Depth, which is a free download. The whole of chapter 6 is on iterators. I have another couple of articles on my C# in Depth site, too:
Iterators, iterator blocks and data pipelines
Iterator block implementation details
As a quick example though:
public IEnumerable<int> EvenNumbers0To10()
{
for (int i=0; i <= 10; i += 2)
{
yield return i;
}
}
// Later
foreach (int x in EvenNumbers0To10())
{
Console.WriteLine(x); // 0, 2, 4, 6, 8, 10
}
To implement IEnumerable<T> for a type, you can do something like:
public class Foo : IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
yield return "x";
yield return "y";
}
// Explicit interface implementation for nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator(); // Just return the generic version
}
}
(I assume C# here)
If you have a list of custom objects you can just use the foreach in the same way as you do with any other object:
List<MyObject> myObjects = // something
foreach(MyObject myObject in myObjects)
{
// Do something nifty here
}
If you want to create your own container you can use the yield keyword (from .Net 2.0 and upwards I believe) together with the IEnumerable interface.
class MyContainer : IEnumerable<int>
{
private int max = 0;
public MyContainer(int max)
{
this.max = max;
}
public IEnumerator<int> GetEnumerator()
{
for(int i = 0; i < max; ++i)
yield return i;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
And then use it with foreach:
MyContainer myContainer = new MyContainer(10);
foreach(int i in myContainer)
Console.WriteLine(i);
From MSDN Reference:
The foreach statement is not limited to IEnumerable types and can be applied to an instance of any type that satisfies the following conditions:
has the public parameterless GetEnumerator method whose return type is either class, struct, or interface type,
the return type of the GetEnumerator method has the public Current property and the public parameterless MoveNext method whose return type is Boolean.
If you declare those methods, you can use foreach keyword without IEnumerable overhead. To verify this, take this code snipped and see that it produces no compile-time error:
class Item
{
public Item Current { get; set; }
public bool MoveNext()
{
return false;
}
}
class Foreachable
{
Item[] items;
int index;
public Item GetEnumerator()
{
return items[index];
}
}
Foreachable foreachable = new Foreachable();
foreach (Item item in foreachable)
{
}

Categories