Search code examples
c#linqcollectionbase

How can LINQ actions be performed on a CollectionBase?


I am coding a C# forms application and I have the following collection for a PropertyGrid control:

public class CustomWebpageJavaScriptFunctionCollection : CollectionBase, ICustomTypeDescriptor
{
    public void Add(CustomWebpageJavaScriptFunction obj)
    {
        this.List.Add(obj);
    }

    public void Remove(CustomWebpageJavaScriptFunction obj)
    {
        this.List.Remove(obj);
    }

    public CustomWebpageJavaScriptFunction this[int index]
    {
        get
        {
            return (CustomWebpageJavaScriptFunction)this.List[index];
        }
    }

    public String GetClassName()
    {
        return TypeDescriptor.GetClassName(this, true);
    }

    public AttributeCollection GetAttributes()
    {
        return TypeDescriptor.GetAttributes(this, true);
    }

    public String GetComponentName()
    {
        return TypeDescriptor.GetComponentName(this, true);
    }

    public TypeConverter GetConverter()
    {
        return TypeDescriptor.GetConverter(this, true);
    }

    public EventDescriptor GetDefaultEvent()
    {
        return TypeDescriptor.GetDefaultEvent(this, true);
    }

    public PropertyDescriptor GetDefaultProperty()
    {
        return TypeDescriptor.GetDefaultProperty(this, true);
    }

    public object GetEditor(Type editorBaseType)
    {
        return TypeDescriptor.GetEditor(this, editorBaseType, true);
    }

    public EventDescriptorCollection GetEvents(Attribute[] attributes)
    {
        return TypeDescriptor.GetEvents(this, attributes, true);
    }

    public EventDescriptorCollection GetEvents()
    {
        return TypeDescriptor.GetEvents(this, true);
    }

    public object GetPropertyOwner(PropertyDescriptor pd)
    {
        return this;
    }


    /// <summary>
    /// Called to get the properties of this type. Returns properties with certain
    /// attributes. this restriction is not implemented here.
    /// </summary>
    /// <param name="attributes"></param>
    /// <returns></returns>
    public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        return GetProperties();
    }

    /// <summary>
    /// Called to get the properties of this type.
    /// </summary>
    /// <returns></returns>
    public PropertyDescriptorCollection GetProperties()
    {
        // Create a collection object to hold property descriptors
        PropertyDescriptorCollection pds = new PropertyDescriptorCollection(null);

        // Iterate the list of employees
        for (int i = 0; i < this.List.Count; i++)
        {
            // Create a property descriptor for the employee item and add to the property descriptor collection
            CustomWebpageJavaScriptFunctionCollectionPropertyDescriptor pd = new CustomWebpageJavaScriptFunctionCollectionPropertyDescriptor(this, i);
            pds.Add(pd);
        }
        // return the property descriptor collection
        return pds;
    }
}

How is the best way to perform LINQ queries on the above collection?

For example, how can I perform a .Where() action on the contents of the CollectionBase List?


Solution

  • LINQ requires generic enumerables, CollectionBase is non-generic. Try doing OfType<object>() first, then you can use LINQ on the IEnumerable<object> instance.

    Edit: As noted in the comments, you can also use Cast<object>(). The difference between the two methods is that OfType will include elements which can be cast to the specified type in the enumeration and skip the rest, whilst Cast requires that all elements can be cast to the type (otherwise an exception is thrown). Cast is faster, since it skips the check and does the cast straight away.

    Cast iterator source:

    foreach (object obj in source) yield return (TResult)obj;
    

    OfType iterator source:

    foreach (object obj in source) {
        if (obj is TResult) yield return (TResult)obj;
    }