tags:

views:

148

answers:

4

I override a list in VB.

In C# the code compiles and looks like this:

class MyObjectCollection : IList
{
    ...
    /// <summary>
    /// Gets or sets the element at the specified index.
    /// </summary>
    public MyObject this[int index]
    {
        get { return (MyObject)innerArray[index]; }
        set { innerArray[index] = value; }
    }
    ...
}

in VB.NET I transform:

Class MyObjectCollection
    Implements IList        
    ...

    ''' <summary> '
    ''' Gets or sets the element at the specified index. '
    ''' </summary> '
    Default Public Overrides Property Item(ByVal index As Integer) As MyObject
      Get
        Return DirectCast(innerArray(index), MyObject)
      End Get
      Set(ByVal value As MyObject)
        innerArray(index) = value
      End Set
    End Property
    ...
End Class

Error:

'Public Overrides Default Property Item(index As Integer) As MyObject' and 'Public Default Property Item(index As Integer) As Object' cannot overload each other because they differ only by return types

Whole collection class in C#

public class MyObjectCollection : IList
{
    private ArrayList innerArray;

    public MyObjectCollection()
    {
        innerArray = new ArrayList();
    }

    public int Count
    {
        get { return innerArray.Count; }
    }

    public bool IsFixedSize
    {
        get { return false; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool IsSynchronized
    {
        get { return false; }
    }

    object ICollection.SyncRoot
    {
        get { return null; }
    }

    public MyObject this[int index]
    {
        get { return (MyObject)innerArray[index]; }
        set { innerArray[index] = value; }
    }

    public int Add(MyObject value)
    {
        int index = innerArray.Add(value);

        return index;
    }

    public void AddRange(MyObject[] array)
    {
        innerArray.AddRange(array);
    }

    public void Clear()
    {
        innerArray.Clear();
    }

    public bool Contains(MyObject item)
    {
        return innerArray.Contains(item);
    }

    public bool Contains(string name)
    {
        foreach (MyObject spec in innerArray)
            if (spec.Name == name)
                return true;

        return false;
    }

    public void CopyTo(MyObject[] array)
    {
        innerArray.CopyTo(array);
    }

    public void CopyTo(MyObject[] array, int index)
    {
        innerArray.CopyTo(array, index);
    }

    public IEnumerator GetEnumerator()
    {
        return innerArray.GetEnumerator();
    }

    public int IndexOf(MyObject value)
    {
        return innerArray.IndexOf(value);
    }

    public int IndexOf(string name)
    {
        int i = 0;

        foreach (MyObject spec in innerArray)
        {
            if (spec.Name == name)
                return i;

            i++;
        }

        return -1;
    }

    public void Insert(int index, MyObject value)
    {
        innerArray.Insert(index, value);
    }

    public void Remove(MyObject obj)
    {
        innerArray.Remove(obj);
    }

    public void Remove(string name)
    {
        int index = IndexOf(name);
        RemoveAt(index);
    }

    public void RemoveAt(int index)
    {
        innerArray.RemoveAt(index);
    }

    public MyObject[] ToArray()
    {
        return (MyObject[])innerArray.ToArray(typeof(MyObject));
    }

    #region Explicit interface implementations for ICollection and IList
    void ICollection.CopyTo(Array array, int index)
    {
        CopyTo((MyObject[])array, index);
    }

    int IList.Add(object value)
    {
        return Add((MyObject)value);
    }

    bool IList.Contains(object obj)
    {
        return Contains((MyObject)obj);
    }

    object IList.this[int index]
    {
        get
        {
            return ((MyObjectCollection)this)[index];
        }
        set
        {
            ((MyObjectCollection)this)[index] = (MyObject)value;
        }
    }

    int IList.IndexOf(object obj)
    {
        return IndexOf((MyObject)obj);
    }

    void IList.Insert(int index, object value)
    {
        Insert(index, (MyObject)value);
    }

    void IList.Remove(object value)
    {
        Remove((MyObject)value);
    }
    #endregion
}
A: 

EDIT: the full class shows that in the C# version you have two indexers. One is declared as an explicit implementation for the IList indexer:

object IList.this[int index] 
{ 
    get 
    { 
        return ((MyObjectCollection)this)[index]; 
    } 
    set 
    { 
        ((MyObjectCollection)this)[index] = (MyObject)value; 
    } 
} 

This is why you can also have a typed indexer which differs only in return type.

You'll need to do the same thing in VB.net but my VB.net skills aren't up to the job - I can't see how to do an explicit interface implementation in VB.net.

Alternatively, you'll need to use the generic version of IList to have a specifically typed indexer. Here's the C# version:

    class MyObjectCollection : IList<MyObject>
    {
        private readonly MyObject[] innerArray;

        public MyObject this[int index] 
        { 
            get { return (MyObject)innerArray[index]; } 
            set { innerArray[index] = value; } 
        } 
    } 
Daniel Renshaw
I added in edit the code
serhio
My understanding is that the VB is the problem, not the C#
Marc Gravell
Marc is right. In VB is the problem, and still remains.
serhio
The full C# class shown in the edited question explains why it works in C#. If explicit interface implementations can be done in VB.net then that's the solution there too.
Daniel Renshaw
in VB all interfaces are explicitly implemented. There are no implicit implementations.
serhio
+1  A: 

I'd suggest inheriting from CollectionBase, which exists specifically for creating strongly typed collections.

Public Class MyObjectCollection
   Inherits CollectionBase

Checkout the example.

KMan
+1  A: 

Reflector tells me that you might try:

Private Property System.Collections.IList.Item(ByVal index As Integer) As Object
    Get
        Return Me.Item(index)
    End Get
    Set(ByVal value As Object)
        Me.Item(index) = DirectCast(value, MyObject)
    End Set
End Property

Public Default Property Item(ByVal index As Integer) As MyObject
    Get
        Return DirectCast(Me.innerArray.Item(index), MyObject)
    End Get
    Set(ByVal value As MyObject)
        Me.innerArray.Item(index) = value
    End Set
End Property

No guarantees, though.

Marc Gravell
Does not work: Error: "multiple definitions with identical signature".
serhio
+1  A: 

If I understand the question correctly, you currently have a method like:

Public Overrides Property Item(ByVal index As Integer) As MyObject
  Get
    Return DirectCast(innerArray(index), MyObject)
  End Get
  Set(ByVal value As MyObject)
    innerArray(index) = value
  End Set
End Property

You also have a method to implement the IList interface, which will look like:

Public Property Item(ByVal index As Integer) As Object Implements IList.Item
    Get
        Return DirectCast(innerArray(index), MyObject)
    End Get
    Set(ByVal value As Object)
        innerArray(index) = value
    End Set

End Property

This doesn't work because the method names are the same, but the return types are different. What you need to do is change the name of the IList implementation method.

Try something like:

Public Property IList_Item(ByVal index As Integer)As Object Implements IList.Item
    Get
        Return DirectCast(innerArray(index), MyObject)
    End Get
    Set(ByVal value As Object)
        innerArray(index) = value
    End Set

End Property
David_001
Maybe better even **Private** Property IList_Item ... Implements IList.Item
serhio