示例程序如下:
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)
它会解决 T
至 int
,但事实仍然是 Foo
在Bar
仍然没有与实际采用 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/