C#: specialized template method - Error: Type '…' already defines a member called '…' with the same parameter types

前端 未结 2 1382
-上瘾入骨i
-上瘾入骨i 2021-01-23 13:02

I\'m quite new to C# and currently developing an application using the EntityFramework. I would like to extend the functionality of the database context class, so that I can cal

相关标签:
2条回答
  • 2021-01-23 13:39

    I'd recommend (besides of reading about generics and C# in general) to configure the pool with desired types on run time, store them in dictionaries and use the Type as key, i.e. something along the following lines...:

    //...
    
    // configuration, maybe factor out to a dedicated class...
    private readonly IDictionary<System.Type, IQueryable> m_SupportedPools =
        new Dictionary<System.Type, IQueryable>();
    
    // add this queryable, note that type inference works here
    public void AddToPool<T>(IQueryable<T> p_Queryable)
    {
        m_SupportedPools.Add(typeof(T), p_Queryable);
    }
    
    public IQueryable<T> GetPool<T>()
    {
        IQueryable t_Set = null;  
        if (m_SupportedQueries.TryGetValue(typeof(T), out t_Set)) {
            return t_Set as IQueryable<T>;
        } else {
            return null;
        }
    }
    
    0 讨论(0)
  • 2021-01-23 13:40

    Unfortunately, in C#, you cannot overload a method by using a generic type constraint like this. You will have to give them different names like this

    public class TestContext : DbContext
    {
        public DbSet<TestA> ATests { get; set; }
        public DbSet<TestB> BTests { get; set; }
    
        public IQueryable<T> getPoolA<T>() where T : TestA {
           return (IQueryable<T>)ATests;
        }
        public IQueryable<T> getPoolB<T>() where T : TestB {
           return (IQueryable<T>)BTests;
        }
    }
    

    Another solution would be to do something like this:

    public class TestContext : DbContext
    {
        public DbSet<TestA> ATests { get; set; }
        public DbSet<TestB> BTests { get; set; }
    
        public IQueryable<T> getPool<T>() {
           return (typeof(T) == typeof(TestA))
                      ? (IQueryable<T>)ATests
                      : (IQueryable<T>)BTests;
        }
    }
    

    Now, you can make this even cleaner, since IQueryable<T> is covariant in T, you can avoid casting:

    public class TestContext : DbContext
    {
        public DbSet<TestA> ATests { get; set; }
        public DbSet<TestB> BTests { get; set; }
    
        public IQueryable<T> getPool<T>() {
           return (typeof(T) == typeof(TestA)) ? ATests : BTests;
        }
    }
    

    If you want to avoid testing for types you can do something like this:

    public class TestContext : DbContext
    {
        readonly Dictionary<Type, object> _sets;
    
        public DbSet<TestA> ATests { get; set; }
        public DbSet<TestB> BTests { get; set; }
    
        public TestContext()
        {
            _sets = new Dictionary<Type, object>
            {
                { typeof(TestA), ATests },
                { typeof(TestB), BTests }
            }
        }
    
        public IQueryable<T> getPool<T>() {
           return (IQueryable<T>)_sets[typeof(T)];
        }
    }
    
    0 讨论(0)
提交回复
热议问题