FCin
FCin

Reputation: 3915

Cast generics based on condition

I am trying to return derived class, but for some implementations I have to provide a little bit more setup, so I have if, but the compiler is not smart enough to know that once it enters the if, it should be able to cast T to Derived1. Is there any other way to do it?

Cannot convert type 'Derived1' to type T

public T GetData<T>(string name) where T : Data
{
    if (_cache.ContainsKey(name))
        return (T)_cache[name];

    using (var db = new LiteDatabase(_dbPath))
    {
        if (typeof(T) is ChartData)
        {
            var collection = db.GetCollection<ChartData>("Data");
            var chunksColl = db.GetCollection<ValuesChunk>(nameof(ValuesChunk));

            var data = collection.Include(d => d.Series).FindOne(Query.EQ(nameof(ChartData.Name), name));
            foreach (var series in data.Series)
            {
                for (int index = 0; index < series.Chunks.Count; index++)
                {
                    var chunk = chunksColl.FindById(series.Chunks[index].ChunkId);
                    series.ChangeChunk(index, chunk);
                }
            }

            _cache.Add(name, data);
            return (Data)data;
        }
        else
        {
            var collection = db.GetCollection<T>();
            return collection.FindOne(Query.EQ(nameof(ChartData.Name), name));
        }
    }
}

public abstract class Data {/*properties*/}
public class ChartData : Data {/*properties*/}
public class ScriptData : Data {/*properties*/}

Upvotes: 0

Views: 104

Answers (1)

Tim Rutter
Tim Rutter

Reputation: 4679

Couple of mistakes in the above, this works (whether its the best design is a different question):

public T Get<T>() where T : Base
{
    if (typeof(T) == typeof(Derived1)) //correction to this line
    {
        var derived = new Derived1();
        derived.Property1 = 5;
        return derived as T; //correction to this line
    }
    else
    {
        // return (T)myMethod;
    }

    return null;
}

or with your edited version:

public T GetData<T>(string name) where T : Data
{
    if (_cache.ContainsKey(name))
        return (T)_cache[name];

    using (var db = new LiteDatabase(_dbPath))
    {
        if (typeof(T) == typeof( ChartData)) //<======CORRECTION HERE
        {
            var collection = db.GetCollection<ChartData>("Data");
            var chunksColl = db.GetCollection<ValuesChunk>(nameof(ValuesChunk));

            var data = collection.Include(d => d.Series).FindOne(Query.EQ(nameof(ChartData.Name), name));
            foreach (var series in data.Series)
            {
                for (int index = 0; index < series.Chunks.Count; index++)
                {
                    var chunk = chunksColl.FindById(series.Chunks[index].ChunkId);
                    series.ChangeChunk(index, chunk);
                }
            }

            _cache.Add(name, data);
            return data as Data;//<======CORRECTION HERE
        }
        else
        {
            var collection = db.GetCollection<T>();
            return collection.FindOne(Query.EQ(nameof(ChartData.Name), name));
        }
    }
}

Upvotes: 3

Related Questions