Rahul
Rahul

Reputation: 57

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

Below are the errors in the Error List.

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  

A .NET fiddle with success and fail scenarios here

Upvotes: 4

Views: 708

Answers (2)

Sweeper
Sweeper

Reputation: 274358

The reason why the compiler gave out so many errors is because it expected an identifier in the <>, but you put a keyword (string) there. The compiler got confused as a result, and the parsing got very wrong. This is also why there are way fewer errors if you use Guid, because Guid is an identifier. But replacing string with Guid doesn't do what you expect either.

You seem to want DemoRepository to only implement IDemoRepository in a very specific case, i.e. when K is string.

Note that the requirement for implementing IDemoRepository is that it should have a generic Get method, being able to take any type K, and returns a Dto.Message. That is what's meant by:

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

public interface IDemoRepository : IGet<Dto.Message>
{

}

I suppose that's not what you actually want IDemoRepository to require? If you only want it to require a non generic Get method. that takes a specific type K, which can be chosen by the implementer, then you can do something like this:

// 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)
    {
        ...
    }
}

Upvotes: 4

Loocid
Loocid

Reputation: 6451

The interface specifies that Get should take a generic parameter but you're trying to define it using a string parameter.

Either change your DemoRepository to make Get generic (which doesn't look like it'll work in your case since you want to use .ToLower).

Or change your Get to be non-generic.

Upvotes: 0

Related Questions