Question

I am pretty new to Generic class in C#. I was trying to create one and ran into compiler error that I am not sure how to get around it.

Basically, I have a class G that implements ICollection

public class G<T> : ICollection<T> where T : IEqualityComparer
{
    private ArrayList _members = new ArrayList();

    public void Add(T item)
    {
        throw new NotImplementedException();
    }

    public void Clear()
    {
        throw new NotImplementedException();
    }

    public bool Contains(T item)
    {
        throw new NotImplementedException();
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        throw new NotImplementedException();
    }

    public int Count
    {
        get { throw new NotImplementedException(); }
    }

    public bool IsReadOnly
    {
        get { throw new NotImplementedException(); }
    }

    public bool Remove(T item)
    {
        throw new NotImplementedException();
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (var item in _members)
        {
            yield return (T)item;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

I wanted to be able to do comparison in G and Find item in G, so I have put a constraint that T has to be implementing IEqualityComparer. Then, I have an actual class called IntegerClass that implement IEqualityComparer as below. So far, so good, no compiler error.

public class IntegerClass : IEqualityComparer<int>
{
    public bool Equals(int x, int y)
    {
        throw new NotImplementedException();
    }

    public int GetHashCode(int obj)
    {
        throw new NotImplementedException();
    }
}

However, when I tried to create an instance of G above. I got a compiler error.

class Program
{
    static void Main(string[] args)
    {
        G<IntegerClass> i = new G<IntegerClass>();
    }
}

The error is:

The type 'TestGeneric.IntegerClass' cannot be used as type parameter 'T' in the generic type or method 'TestGeneric.G<T>'. 
There is no implicit reference conversion from 'TestGeneric.IntegerClass' to 'System.Collections.IEqualityComparer'

Could someone pinpoint what I have overlooked? Why would I need conversion? All I did was replacing class T with IntegerClass that implements IEqualityComparer interface. What should I do otherwise? I am new to this generic stuff, but have found it quite useful. I am thinking it could be very useful if I understand it correctly. Please help.

Update: Based on some suggestion, I saw what was wrong and I updated the code as follow:

   public class IntegerClass :  IEqualityComparer
    {
        public bool Equals(object x, object y)
        {
            throw new NotImplementedException();
        }
    public int GetHashCode(object obj)
    {
        throw new NotImplementedException();
    }
}
public class G<T> : ICollection<T> where T : IEqualityComparer
{
    private ArrayList _members = new ArrayList();

    public void Add(T item)
    {
        throw new NotImplementedException();
    }

    public void Clear()
    {
        throw new NotImplementedException();
    }

    public bool Contains(T item)
    {
        throw new NotImplementedException();
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        throw new NotImplementedException();
    }

    public int Count
    {
        get { throw new NotImplementedException(); }
    }

    public bool IsReadOnly
    {
        get { throw new NotImplementedException(); }
    }

    public bool Remove(T item)
    {
        throw new NotImplementedException();
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (var item in _members)
        {
            yield return (T)item;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

I think it might work but I got the warning below:

'TestGeneric.IntegerClass.Equals(object, object)' hides inherited member 'object.Equals(object, object)'. Use the new keyword if hiding was intended.

I know object has an Equals methods but the warning does not make sense. Should it say use the new keyword if hiding was NOT intended?

Was it helpful?

Solution

Your constraint refers to the non-generic System.Collections.IEqualityComparer interface, which is not the same as IEqualityComparer<T>.
You could fix that error by specify the generic type in the constraint.


However, that's not what you want; an IEqualityComparer is a class that compares other things.

You want where T : IEquatable<T>.

OTHER TIPS

change your IntegerClass like below.

public class IntegerClass : IEqualityComparer<IntegerClass>
{
    public bool Equals(IntegerClass IC1, IntegerClass IC2)
    {
        throw new NotImplementedException();
    }

    public int GetHashCode(IntegerClass obj)
    {
        throw new NotImplementedException();
    }
}

Or you could resort it to the fact that Objects has an equality function. Hence, this would work

    public interface IMyComparer
    {
        object Comparer { get; }
    }

    public class IntegerClass : IMyComparer, IEqualityComparer<int>
    {

        public object Comparer { get { return this; } }

        public bool Equals(int x, int y)
        {
            throw new NotImplementedException();

        }

        public int GetHashCode(int obj)
        {
            throw new NotImplementedException();
        }
   }
   public class G<T> : ICollection<T> where T : IMyComparer
   {
     Your implementations
   }

Hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top