开发者

Compiler says I am not implementing my interface, but I am?

Okay, I have two namespaces. One contains my interface and one contains the implementing class. Like this:

namespace Project.DataAccess.Interfaces
{
    public interface IAccount
    {
        string SomeMethod();
    }
}

namespace Project.DataAccess.Concrete
{
    class Account : P开发者_开发技巧roject.DataAccess.Interfaces.IAccount
    {
        string SomeMethod()
        {
            return "Test";
        }
    }
}

With this code I get an error:

'Project.DataAccess.Concrete.Account' does not implement interface member 'Project.DataAccess.Interfaces.IAccount.SomeMethod'. 'Project.DataAccess.Concrete.Account.SomeMethod' cannot implement an interface member because it is not public

If I make the class and method public it works fine. But if I instead qualify the method name with the interface name, that fixes it too. Why? Ex:

namespace Project.DataAccess.Concrete
{
    class Account : Project.DataAccess.Interfaces.IAccount
    {
        string IAccount.SomeMethod()
        {
            return "Test";
        }
    }
}

Why does this fix it? And why does it have to be public if I don't do that?

To be clear

I am well aware that making it public fixes it. Making the method signature look like this WITHOUT making anything public fixes it:

string IAccount.SomeMethod()

Why?


Interface implementations need to be public or explicit:

Public:

class Account : IAccount
{
    public string SomeMethod()
    {
        return "Test";
    }
}

Explicit:

class Account : IAccount
{
    string IAccount.SomeMethod()
    {
        return "Test";
    }
}

The default access modifier in C# is private if you do not specify the access modifier.


You have 2 basic options when implementing intefaces: implicit or explicit. Implicit implementation takes on the form of a public method or property, while explicit is in the form of a method or property prefaced with the IFoo. modifier that is otherwise not public.

interface IFoo
{
    void Bar();
}

class FooA : IFoo
{
    public void Bar() { }
}

class FooB : IFoo
{
    void IFoo.Bar() { }
}

The difference here is that in the case of FooA, void Bar is part of the publicly visible API of the class. Code can call Bar via the instance of the class.

FooA foo = new FooA(); 
foo.Bar(); // legal

In the case of FooB, void Bar is not part of the publicly visible API of the class. The method can still be called, but it must explicitly be called via the interface.

FooB foo = new FooB();
foo.Bar(); // not legal
IFoo myFoo = foo;
myFoo.Bar(); // legal

Your code does not compile because it walks in the uncharted waters between an implicit and explicit interface implementation. You saw that with your change, you had legally defined an explicit implementation, which is why that particular version compiles. Otherwise, you've also found that the public modifer is needed to make the non-explicit version compile.


Methods implementing interface needs to be public. In your later case, you are declaring it explicitly. This is what specification says about explicit interface implementation.

Explicit interface member implementations have different accessibility characteristics than other members. Because explicit interface member implementations are never accessible through their fully qualified name in a method invocation or a property access, they are in a sense private. However, since they can be accessed through an interface instance, they are in a sense also public.


'Project.DataAccess.Concrete.Account.SomeMethod' cannot implement an interface member because it is not public

namespace Project.DataAccess.Concrete
{
    public class Account : IAccount    
    {
        public string IAccount.SomeMethod()
        {
            return "Test";
        }
    }
}


You're not mentioning in your class declaration that you'll be implementing IAccount.

Your class declaration should look like this:

class Account : IAccount
{ 
  //Implementation here.
}

Also, what's happening is that you're using the "default" protection level for Account, and that protection level isn't "public", but an Interface (IAccount) defines public methods by default.

So, when you preface both the Class and Method names with public you're actually implementing the interface. Likewise, when you declare SomeMethod as

IAccount.SomeMethod()
{
   //Implementation Here
}

what you're doing is Explicitly Implementing the interface.


I think declaring it explicitly with string IAccount.SomeMethod() works because .NET knows that this implementation of the method can only be accessed through the interface, and so it carries over the public visibility from the interface. In other words, since you are explicitly saying it is an interface member, the compiler can imply that it has to be public, so you don't have to re-state the obvious.

This is also discussed here: http://msdn.microsoft.com/en-us/library/aa664591%28v=vs.71%29.aspx

It is a compile-time error for an explicit interface member implementation to include access modifiers, and it is a compile-time error to include the modifiers abstract, virtual, override, or static.

Explicit interface member implementations have different accessibility characteristics than other members. Because explicit interface member implementations are never accessible through their fully qualified name in a method invocation or a property access, they are in a sense private. However, since they can be accessed through an interface instance, they are in a sense also public.


class Account : IAccount    
    {         
    public string SomeMethod()         
    {            
     return "Test";         
    }     
    } 

Tell your class to implement the interface. Using the Interface.Method name explicitly implements the method (but i'm not sure why or how) and you need to make them public.

You want to use Interface.Method to explicitly implement an interface requirement when the class already has a member of the same name

class MyClass : IAccount
{
   public int SomeMethod() {}
   public string IAccount.SomeMethod() {}
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜