tags:

views:

94

answers:

2

What I have?

I have an abstract class, QueryExecutor and derived class, SqlQueryExecutor shown below.

abstract class QueryExecutor<T>
{
    public abstract T Execute();
}

class SqlQueryExecutor<T> : QueryExecutor<T> where T:ICollection
{
    public override T Execute()
    {
        Type type = typeof(T);

        // Do common stuff
        if (type == typeof(ProfileNodeCollection))
        {
            ProfileNodeCollection nodes = new ProfileNodeCollection();
            // Logic to build nodes
            return (T)nodes;
        }
        else
        {
            TreeNodeCollection nodes = new TreeNodeCollection();
            Logic to build nodes

            return (T)nodes;                
        }
    }
}

What I want to do?

In the implementation of Execute() method, I want to construct the appropriate ICollection object and return it.

What problem am I facing?

In Execute() method, the line, return (T)nodes; shows the following compile time error:

Cannot convert type 'WebAppTest.ProfileNodeCollection' to 'T'

Any idea how can I solve this?

Thanks in advance!

+4  A: 

Well, a simple way of fixing it is to just make the compiler less aware of what's going on, so that it'll just defer it to the CLR:

return (T)(object)nodes;

You could put this in a single place and use an implicit conversion to object on assignment:

object ret;
// Do common stuff
if (type == typeof(ProfileNodeCollection))
{
    ProfileNodeCollection nodes = new ProfileNodeCollection();
    // Logic to build nodes
    ret = nodes;
}
else
{
    TreeNodeCollection nodes = new TreeNodeCollection();
    Logic to build nodes

    ret = nodes;
}
return (T)ret;

It's not terribly pleasant, but it should work. It would probably be nicer to create separate derived classes for different collection types though - possibly putting common code in an abstract base class.

Jon Skeet
+1  A: 

I would chose to separate concerns here. You could even have a QueryExecutor factory that would provide the right QueryExecutor accordingly to the type of collection.

class ProfileSqlQueryExecutor : QueryExecutor<ProfileNodeCollection>
{
    public override ProfileNodeCollection Execute()
    {
        ProfileNodeCollection nodes = new ProfileNodeCollection();
        // Logic to build nodes
        return nodes;
    }
}

class TreeSqlQueryExecutor : QueryExecutor<TreeNodeCollection>
{
    public override TreeNodeCollection Execute()
    {
        TreeNodeCollection nodes = new TreeNodeCollection();
        Logic to build nodes
        return nodes;                
    }
}
bruno conde