C# 什么是接口类型?

C# 什么是接口类型?,c#,oop,C#,Oop,我听过鸭子输入界面这个词,但一点也不明白它是什么?所以我读了一篇关于这个的维基,他们说: 在使用面向对象编程语言的计算机编程中,duck类型是一种类型类型,其中对象的方法和属性决定有效的语义,而不是从特定类或显式接口的实现继承。概念的名称指的是duck测试 但还是不明白是什么。所以我看到了他们的程序,但他们使用动态关键字调用所有类的quack()&feather()函数 我想请大家用简单的方式解释什么是接口类型以及如何在C#v2.0中实现,因为没有动态关键字 using System; nam

我听过鸭子输入界面这个词,但一点也不明白它是什么?所以我读了一篇关于这个的维基,他们说:

在使用面向对象编程语言的计算机编程中,duck类型是一种类型类型,其中对象的方法和属性决定有效的语义,而不是从特定类或显式接口的实现继承。概念的名称指的是duck测试

但还是不明白是什么。所以我看到了他们的程序,但他们使用
动态
关键字调用所有类的
quack()
&
feather()
函数

我想请大家用简单的方式解释什么是接口类型以及如何在C#v2.0中实现,因为没有
动态
关键字

using System;

namespace DuckTyping 
{  
  public class Duck 
  {
    public void Quack() 
    {
      Console.WriteLine("Quaaaaaack!");
    }

    public void Feathers() 
    {
      Console.WriteLine("The duck has white and gray feathers.");
    }
  }

  public class Person 
  {
    public void Quack()
    {
      Console.WriteLine("The person imitates a duck.");
    }

    public void Feathers() 
    {
      Console.WriteLine("The person takes a feather from the ground and shows it.");
    }
  }

  internal class Program 
  {
    private static void InTheForest(dynamic duck) 
    {
      duck.Quack();
      duck.Feathers();
    }

    private static void Game() 
    {
      Duck donald = new Duck();
      Person john = new Person();
      InTheForest(donald);
      InTheForest(john);
    }

    private static void Main() 
    {
      Game();
    }
  }
}
Duck类型允许将对象传递给期望 某个类型,即使它不是从该类型继承的。它所拥有的一切 要做的是支持中预期类型的方法和属性 按方法使用。我强调最后一句话是有原因的。假设 我们有一个接受duck实例的方法,还有另一个方法 以兔子为例。在动态类型化语言中 支持duck类型,我可以将我的对象作为 只要我的对象支持正在使用的duck的方法和属性 用那种方法。同样,我可以将我的对象传递给第二个方法 只要它支持由调用的rabbit的方法和属性 第二种方法。我的目标是鸭子还是兔子?像 上图,两者都不是,两者都是。在许多(如果不是大多数)动态环境中 语言,我的对象不必支持所有方法和 要传递给需要duck的方法的duck的属性。 对于期望兔子的方法也是如此,它只需要支持 实际使用的预期类型的方法和属性 由方法调用

请参考这篇文章了解Duck类型


它会说这是一种编码方式,您可以告诉编译器:

“嘿,相信我,我知道这个对象支持哪些方法和属性。在我编写代码时,你不需要帮我检查它们。”

运行应用程序后,编译器将执行以下操作: “好吧,让我们看看我是否可以信任你。让我做一些运行时绑定。”

如果您随后犯了错误,例如使用了不受支持的方法,编译器将大叫:“嘿,伙计,这不受支持!检查我的RuntimeBinderException!”C#有一个标称类型系统,因此类型的兼容性是基于它们的名称来完成的。在您的示例中,有两个类使用
Quack
方法,但是无法编写一个方法来获取这两个类的实例并调用它们的
Quack
方法

在C#2中,解决方案是引入一个接口,并让两个类都实现它:

public interface IQuack
{
    void Quack();
}

public class Duck : IQuack { }
public class Human : IQuack { }
现在,您可以创建一个方法,该方法接受一个
IQuack
实例,并可以通过它调用
Human.Quack
Duck.Quack
。在C#中,方法在编译时“早期”解析,因此您需要创建一个支持方法所需操作的命名类型,以便编译能够成功。注意,调用这些方法仍然有一个运行时元素,因为
IQuack.Quack
的实际实现需要在运行时根据参数的实际类型进行解析

在duck类型系统中,在运行之前不会尝试验证方法是否存在。所需的只是一个给定的对象支持该操作,因为它具有正确的名称并接受所需数量的参数(在本例中为零),因此使用了“if it quacks like a duck”表达式

C#2中的Duck键入只能使用反射完成,在这种情况下,您将接受
对象
参数,并自己查找所需的方法:

public static void MakeQuack(object duck)
{
    MethodInfo quackMethod = duck.GetType().GetMethod("Quack", Type.EmptyTypes, null);
    if (quackMethod!=null)
    {
        quackMethod.Invoke(duck, new object[] { });
    }
    else
    {
        throw new ArgumentException("No Quack() method found on target");
    }
}
C#4通过
动态
,使这一点变得更加简单:

public static void MakeQuack(dynamic duck)
{
    duck.Quack();
}

关于Duck键入:

我们不需要知道对象是什么,但我们只想让 对象可以做的事情

示例:

例如,如果下面是我们希望以下对象做的事情

PleaseWalk(new Dog());
PleaseRun(new Duck());
PleaseWalk(new Cup());
PleaseFly(new Man());
PleaseFly(new Bird());
这里是我们请求上面的对象做这些事情后的结果。

所以,我们不需要检查对象是什么,但我们可以让它做一些足够的事情。下面是我用C#编写的代码


@Ewald Stieger@Patrick Fromberg@Lee@John Pluto Solutions@Tarzanbapa@Thomas@BartoszKP您可以使用事件并利用C#最合适的重载函数。 希望它会有用:) 要获得类似鸭子的输入(.Net 4.+):

使用系统集合;
使用System.Collections.Generic;
公共接口
{
void InvokeGetterEvent();
}
公共类AnyValueTypeDuck:IAny
其中V:AnyValueTypeDuck
{
公共静态事件系统;
公共数据;
public void InvokeGetterEvent()
{
调用((V)this);
}
}
//然后创建一些具体的类:
//例如:
公共类LifeConcrete属性:AnyValueTypeDuck
{
}
公共类属性:AnyValueTypeDuck
{
}
//现在,最后使用它:
公共类用户类
{
List allDuckTypes=新列表();
public void GetDucketTypeClass(IAny anyDuckObject)
{
LifeConcreteProperty.GetterEvent+=GetDucketType;
ManaConcreteProperty.GetterEvent+=GetDucketType;
anyDuckObject.InvokeGetterEvent();
//它将传播到事件并调用
//最合适的重载方法(GetDucketType)
LifeConcreteProperty.GetterEvent-=GetDucketType;
ManaConcreteProperty.GetterEvent-=GetDucketType;
}
public void GetDucketType(LifeConcreteProperty originalClass)
{
//你的努力到此为止
private void PleaseWalk(object obj)
    {
        string Method = "Walk";
        MethodInfo walkMethod = obj.GetType().GetMethod(Method, Type.EmptyTypes, null);
        if (walkMethod != null)
        {
            walkMethod.Invoke(obj, new object[] { });
        }
        else
        {
            Console.WriteLine(string.Format("I can not {0} because {1}", Method, WhoAreYou(obj)));
        }
    }

    private string WhoAreYou(object unknown)
    {
        MethodInfo whoAreYou = unknown.GetType().GetMethod("WhoAreYou", Type.EmptyTypes, null);
        return whoAreYou.Invoke(unknown, new object[] { }).ToString();
    }
using System.Collections;
using System.Collections.Generic;
public interface  IAny
{
    void InvokeGetterEvent();
}
 public class AnyValueTypeDuck<T, V> : IAny
    where V : AnyValueTypeDuck<T, V>
 {
    public static event System.Action<V> GetterEvent;
    public T Data;
    public void InvokeGetterEvent()
    {
        GetterEvent.Invoke((V)this);
    }
 }

// Then create some concrete classes:
// Example :
public class LifeConcreteProperty : AnyValueTypeDuck<int, LifeConcreteProperty>
{
}
public class ManaConcreteProperty : AnyValueTypeDuck<float, ManaConcreteProperty>
{
}

// Now to finally use it :
public class UserClass
{
    List<IAny> allDuckTypes = new List<IAny>();

    public void GetDucketTypeClass(IAny anyDuckObject)
    {
        LifeConcreteProperty.GetterEvent += GetDucketType;
        ManaConcreteProperty.GetterEvent += GetDucketType;
        anyDuckObject.InvokeGetterEvent();
        // it will propagate to event and will invoke 
        // best suitable overload method (GetDucketType)
        LifeConcreteProperty.GetterEvent -= GetDucketType;
        ManaConcreteProperty.GetterEvent -= GetDucketType;
    }

    public void GetDucketType(LifeConcreteProperty originalClass)
    {
        // Your efforts go here
        int value =  originalClass.Data;
    }
    public void GetDucketType(ManaConcreteProperty originalClass)
    {
        // Your efforts go here
        float value =  originalClass.Data;
    }
}