简体   繁体   English

C#:专用模板方法-错误:类型“…”已经定义了具有相同参数类型的成员“…”

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

I'm quite new to C# and currently developing an application using the EntityFramework. 我是C#的新手,目前正在使用EntityFramework开发应用程序。 I would like to extend the functionality of the database context class, so that I can call a method getPool() so that it hands out the according DbSet member of the class. 我想扩展数据库上下文类的功能,以便可以调用方法getPool(),以便它分发该类的相应DbSet成员。

I need to implement it as a template as it will be later called from other templates, which are just knowing about the (global) database context object and a type T (having a given superclass) for which they shall query the database. 我需要将其实现为模板,因为稍后会从其他模板中调用它们,这些模板仅知道(全局)数据库上下文对象和要查询数据库的类型T(具有给定的超类)。

Here is what I tried (a bit simplified - original example is too complicated): 这是我尝试的方法(有点简化-原始示例太复杂了):

public class TestContext : DbContext
{
    public DbSet<TestA> ATests { get; set; }
    public DbSet<TestB> BTests { get; set; }

    public IQueryable<T> getPool<T>() where T : TestA {
       return (IQueryable<T>)ATests;
    }
    public IQueryable<T> getPool<T>() where T : TestB {
       return (IQueryable<T>)BTests;
    }
}

The error message is 错误消息是

Error: Type '...' already defines a member called '...' with the same parameter types . 错误:类型“ ...”已经定义了具有相同参数类型的成员“ ...”

And it occurs at the line of the second specialized definition of my template ( public IQueryable<T> getPool<T>() where T : TestB ). 它发生在模板的第二个专门定义的行( public IQueryable<T> getPool<T>() where T : TestB )。

The question is: How to fix this? 问题是:如何解决此问题?

Unfortunately, in C#, you cannot overload a method by using a generic type constraint like this. 不幸的是,在C#中,您不能通过使用这样的通用类型约束来重载方法。 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: 现在,您可以使其更加整洁,因为IQueryable<T>T是协变的,因此可以避免强制转换:

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)];
    }
}

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, ie something along the following lines...: 我建议(除了阅读一般性知识和C#外)在运行时为池配置所需的类型,将它们存储在字典中,并使用Type作为键,即以下几行:

//...

// 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;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C#错误:类型'x'已经定义了一个名为'y'的成员,它具有相同的参数类型 - C# error: Type 'x' already defines a member called 'y' with the same parameter types 错误 CS0111:“程序”类型已经定义了一个名为“Main”的成员,具有相同的参数类型 c# - error CS0111: Type 'Program' already defines a member called 'Main with the same parameter types c# 已经定义了一个使用相同参数类型调用的成员 c# - already defines a member called with the same parameter types c# 类型&#39;Startup&#39;已经定义了一个名为&#39;Configuration&#39;的成员,它具有相同的参数类型 - Type 'Startup' already defines a member called 'Configuration' with the same parameter types 错误 - 已经使用相同的参数类型定义了一个名为“InitializeComponent”的成员 - Error - already defines a member called 'InitializeComponent' with the same parameter types 错误已使用相同的参数类型定义了一个名为“索引”的成员 - Error already defines a member called 'Index' with the same parameter types 错误1类型“ Pay”已经使用相同的参数类型定义了一个名为“ ComputePay”的成员 - Error 1 Type 'Pay' already defines a member called 'ComputePay' with the same parameter types 我该如何修复错误:Type Form1&#39;已经定义了一个名为&#39;Dispose&#39;的成员,它具有相同的参数类型? - How can i fix the error: Type Form1' already defines a member called 'Dispose' with the same parameter types? 类型“Type”已经定义了一个名为“Equals”的成员,在 Equals(object) 上具有相同的参数类型 - Type 'Type' already defines a member called 'Equals' with the same parameter types on Equals(object) 错误2类型&#39;WindowsForms2012Snowman.WindowsForms2012SnowmanForm1&#39;已经定义了具有相同参数类型的名为&#39;Dispose&#39;的成员 - Error 2 Type 'WindowsForms2012Snowman.WindowsForms2012SnowmanForm1' already defines a member called 'Dispose' with the same parameter types
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM