在 C# 中实现接口的泛型方法时出现奇怪的错误。这里到底出了什么问题?

I am getting weird errors while implementing a generic method of an interface in C#. What exactly is going wrong here?

public interface IGet<T>
{
    T Get<K>(K id);
}

public interface IDemoRepository : IGet<Dto.Message>
{

}

public class DemoRepository : IDemoRepository
{
    public Dto.Message Get<string>(string messageId)
    {
        using (var db = new AppDbContext())
        {
            return db.Messages
                .FirstOrDefault(f => f.MessageId.ToLower() == messageId.ToLower());
        }
    }
}

以下是错误列表中的错误。

Severity    Code    Description
Error       CS1001  Identifier expected
Error       CS1003  Syntax error, '>' expected  
Error       CS1003  Syntax error, '(' expected  
Error       CS1001  Identifier expected 
Error       CS1003  Syntax error, ',' expected  
Error       CS1003  Syntax error, ',' expected  
Error       CS8124  Tuple must contain at least two elements.   
Error       CS1001  Identifier expected 
Error       CS1026  ) expected  
Error       CS0535  'DemoRepository' does not implement interface member 'IGet<Dto.Message>.Get<K>(K)'  
Error       CS0103  The name 'messageId' does not exist in the current context  

具有成功和失败场景的 .NET fiddle here

接口指定 Get 应采用通用参数,但您正试图使用​​ string 参数来定义它。

要么改变你的 DemoRepository 使 Get 通用(这看起来不适合你的情况,因为你想使用 .ToLower)。

或者将您的 Get 更改为非通用的。

编译器给出这么多错误的原因是因为它期望在 <> 中有一个标识符,但你在那里放了一个关键字 (string)。编译器因此变得混乱,解析变得非常错误。这也是为什么使用 Guid 时错误会少得多的原因,因为 Guid 是一个标识符。但是将 string 替换为 Guid 也不符合您的预期。

您似乎希望 DemoRepository 仅在非常具体的情况下实施 IDemoRepository,即当 Kstring.

请注意,实现 IDemoRepository 的要求是它应该具有 generic Get 方法,能够采用 any 输入 K,然后 returns 一个 Dto.Message。这是什么意思:

public interface IGet<T>
{
    T Get<K>(K id);
}

public interface IDemoRepository : IGet<Dto.Message>
{

}

我想这不是您真正想要 IDemoRepository 要求的?如果你只希望它需要一个非通用的 Get 方法。它采用 specific 类型 K,可以由实施者选择,然后你可以这样做:

// I moved the generic parameter K from the method to the interface
public interface IGet<T, K>
{
    T Get(K id);
}

public interface IDemoRepository<K> : IGet<Dto.Message, K>
{

}

// here the implementer chose string as K
public class DemoRepository : IDemoRepository<string>
{
    public Dto.Message Get(string messageId)
    {
        ...
    }
}