c# - 你能解释一下这种泛型行为吗?如果我有解决方法?

标签 c# oop generics implementation

示例程序如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GenericsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            IRetrievable<int, User> repo = new FakeRepository();

            Console.WriteLine(repo.Retrieve(35));
        }
    }

    class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    class FakeRepository : BaseRepository<User>, ICreatable<User>, IDeletable<User>, IRetrievable<int, User>
    {
        // why do I have to implement this here, instead of letting the
        // TKey generics implementation in the baseclass handle it?
        //public User Retrieve(int input)
        //{
        //    throw new NotImplementedException();
        //}
    }

    class BaseRepository<TPoco> where TPoco : class,new()
    {
        public virtual TPoco Create()
        {
            return new TPoco();
        }

        public virtual bool Delete(TPoco item)
        {
            return true;
        }

        public virtual TPoco Retrieve<TKey>(TKey input)
        {
            return null;
        }
    }

    interface ICreatable<TPoco> { TPoco Create(); }
    interface IDeletable<TPoco> { bool Delete(TPoco item); }
    interface IRetrievable<TKey, TPoco> { TPoco Retrieve(TKey input); }
}

此示例程序代表我的实际程序使用的接口(interface),并演示我遇到的问题(在 FakeRepository 中注释掉)。我希望此方法调用一般由基类处理(在我的真实示例中,它能够处理给定的 95% 的情况),允许通过显式指定 TKey 的类型在子类中进行覆盖。我对 IRetrievable 使用什么参数约束似乎并不重要,我永远无法让方法调用落入基类。

此外,如果有人能看到实现这种行为并获得我最终想要的结果的替代方法,我将非常有兴趣看到它。

想法?

最佳答案

该代码无法编译的原因与这个更简单的示例无法编译的原因相同:

public interface IBar
{
    void Foo(int i);
}

public class Bar : IBar
{
    public void Foo<T>(T i)
    {
    }
}

这些方法根本没有相同的签名。是的,您可以调用 someBar.Foo(5)它会解决 Tint ,但事实仍然是 FooBar仍然没有与实际采用 int 的方法相同的签名作为参数。

您可以通过在类型中同时使用非泛型和泛型方法来进一步证明这一点;这不会导致与歧义相关的错误:

public class Bar : IBar
{
    public void Foo(int i)
    {

    }
    public void Foo<T>(T i)
    {
    }
}

至于实际解决你的问题,你可以这样做:

class FakeRepository : BaseRepository<User>, ICreatable<User>, IDeletable<User>, IRetrievable<int, User>
{
    public User Retrieve(int input)
    {
        return Retrieve<int>(input);
    }
}

这意味着 FakeRespository具有 Retrieve 的通用和非通用版本, 但最终所有调用仍定向到通用版本。

关于c# - 你能解释一下这种泛型行为吗?如果我有解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13126215/

相关文章:

c# - 如何在ElasticSearch NEST 7.x中为具有文档ID的文档列表编制索引

c# - NLog 全局属性

java - 调用父类(super class)型方法会创建一个新的父类(super class)型对象吗?

Scala 类型推断不适用于泛型案例类和 lambda

java - Foo 的实现类可以称为 Foo 的扩展类吗?

c# - SQL 异常 - 与网络相关或特定于实例。 SQL Express "It works on my machine"问题

c++ - 尝试在 C++ 函数中添加数组的整数失败

java 函数返回比 Boolean 更多的状态类型

ios - 是否可以在 Objective-C 泛型中反省数组的类型——Xcode 7+

c# - Windows 8 商店应用程序 C# 中的 OpenGL 支持