C# 为什么从类调用接口成员会生成错误?

问题描述 投票:0回答:2

所以我有一个界面:

interface IFoo
{
    int Bar();
    int this[int i] {get; set;}
}

以及从它派生的类

class Foo : IFoo
{
    public int IFoo.Bar()
    {
        //Implementation
    {
    public int IFoo.this[int i]
    {
        //Implementation
    }
}

现在,我尝试这样做:

var fooey = new Foo();
int i = Fooey.Bar();

或者这个:

int i = Fooey[4];

我希望这些能够正常工作。 但是,编译器会生成错误,就好像此类成员不存在一样。 这是为什么? 我知道我可以强制转换

Foo as IFoo
,但我也知道强制转换会降低性能成本,这通常是首先使用接口的原因。

编辑1: 这些是生成的错误

“Foo”不包含“Bar”的定义,并且找不到接受“Foo”类型的第一个参数的扩展方法“Bar”(您是否缺少 using 指令或程序集引用?)

“无法将索引应用于‘Foo’类型的表达式”

c# syntax compiler-errors
2个回答
11
投票

您已经显式实现了

IFoo
,这意味着只能通过显式键入到
IFoo
的引用来访问其成员:

// This will work
Foo fooey = new Foo();
int i = ((IFoo)fooey).Bar();

如果您希望成员在不进行强制转换的情况下可见,那么在您的实现中只需使用成员名称本身,而不用接口名称作为前缀:

class Foo : IFoo
{
    public int Bar() { /* implementation */ }
    public int this[int i] { /* implementation */ }
}

// now this will also work:
Foo fooey = new Foo();
int i = fooey.Bar();

0
投票

我不相信你正在实例化你的课程。 这段代码应该适合你:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            IFoo foo = new Foo();
            Console.WriteLine("Will return 10: {0}", foo.Bar());

            foo[10] = 20;
            Console.WriteLine("Will return 20: {0}", foo[10]);
        }
    }

    interface IFoo
    {
        int Bar();
        int this[int i] { get; set; }
    }

    class Foo : IFoo
    {
        private int[] array = new int[100];
        public int Bar()
        {
            return 10;
        }

        public int this[int i]
        {
            get
            {
                if (i >= 100)
                {
                    throw new IndexOutOfRangeException("Maximum range is 100");
                }
                return array[i];
            }
            set
            {
                array[i] = value;
            }
        }
    }
}

最后,减少强制转换并不是使用接口的唯一原因。 当您使用“工厂模式”和一般抽象时,接口也可以很好地工作,这在“合同模式”中得到了最好的描述。 换句话说,您可以拥有从 IFoo 继承的多个类,并且可以将它们传递到利用该协定的代码的其他部分,而无需实际知道实际实现该协定(接口)的类。

© www.soinside.com 2019 - 2024. All rights reserved.