C# 何时使用接口类型的变量而不是具体类型的变量

C# 何时使用接口类型的变量而不是具体类型的变量,c#,C#,我有一个从接口派生的类。现在这个类必须实现接口中的所有方法,它还定义了另外两个方法。 现在我的问题是,这样做的好处/用例是什么: IMyInterface varInt= new ConcreteImp(); 结束 我看到这个模式在代码块的每个地方都使用,但不确定为什么要使用它。假设您希望在代码的其他地方能够将IMyInterface的不同实现分配给varInt变量。然后,需要使用IMyInterface类型声明该变量 或者,如果您想让任何代码读者清楚地知道,您打算对varInt执行的所有操作

我有一个从接口派生的类。现在这个类必须实现接口中的所有方法,它还定义了另外两个方法。 现在我的问题是,这样做的好处/用例是什么:

IMyInterface varInt= new ConcreteImp();
结束


我看到这个模式在代码块的每个地方都使用,但不确定为什么要使用它。

假设您希望在代码的其他地方能够将IMyInterface的不同实现分配给varInt变量。然后,需要使用IMyInterface类型声明该变量


或者,如果您想让任何代码读者清楚地知道,您打算对varInt执行的所有操作都是使用IMyInterface定义的接口,那么类型声明会清楚地说明这一点。

假设您希望在代码的其他地方,能够将IMyInterface的不同实现分配给varInt变量。然后,需要使用IMyInterface类型声明该变量


或者,如果您想让任何代码读者清楚地知道,您打算对varInt所做的一切就是使用IMyInterface定义的接口,那么类型声明会清楚地说明这一点。

当您需要在派生类use接口中实施功能时


当您需要将数据从超类传递到子类时,您可以使用具体的类。它是接口和子类背后的基本oop思想。

当您需要在派生类使用接口中强制实现功能时


当您需要将数据从超类传递到子类时,您可以使用具体的类。它是接口和子类背后的基本oop思想。

使用接口的好处在于减少部件对软件组件具体实现的依赖性。在您发布的一行中,您将无法看到好处。用户可以从该界面中获得好处

编辑:你很乐意

例如,假设您有一个方法,它接受一个像so RentIMovie这样的接口。另一个人将能够编写Rent方法的实现,而不知道调用该方法时将传入的IMovie类型的细节。然后,您将能够创建多个不同的IMovie实现,这些实现可能有不同的计费方法,但Rent method不必考虑这一点

void Rent(IMovie movie)
{
    var price = movie.Price();
    movie.MarkReserved();
}

public interface IMovie { }

public class Oldie : IMovie
{
    private decimal _oldieRate = 0.8;

    public decimal Price()
    {
        return MainData.RentPrice * _oldieRate;
    }
    public decimal MarkReserved()
    {
        _oldiesDb.MarkReserved(this, true);
    }
}


public class Blockbuster : IMovie
{
    private decimal _blockbusterRate = 1.2;

    public decimal Price()
    {
        return MainData.RentPrice * _blockbusterRate ;
    }
    public decimal MarkReserved()
    {
        _regularDb.MarkReserved(this, true);
    }
}
这就是为什么接口很有用的例子,但不是很好的代码设计例子

根据经验,您应该编写方法,以便它们需要的输入最少,并且它们的输出在调用时为其他人提供尽可能多的信息。例如,请查看以下签名:

public List<Entity> Filter(IEnumerable<Entity> baseCollection){ ... }
此方法只请求IEnumerable,因此它可以采用不同的集合类型,如List、Entity[]或某些工具返回的自定义类型。但您返回列表,这样就不会立即将调用者限制为仅可枚举元素。例如,她可以立即在返回值上使用Linq


还有更多的好处,比如在单元测试中,您可以创建模拟对象,并告诉它们在与其余代码交互期间如何行为。尽管如此,您现在可以通过虚拟方法使用类来实现这一点。

使用接口的好处在于减少部件对软件组件具体实现的依赖性。在您发布的一行中,您将无法看到好处。用户可以从该界面中获得好处

编辑:你很乐意

例如,假设您有一个方法,它接受一个像so RentIMovie这样的接口。另一个人将能够编写Rent方法的实现,而不知道调用该方法时将传入的IMovie类型的细节。然后,您将能够创建多个不同的IMovie实现,这些实现可能有不同的计费方法,但Rent method不必考虑这一点

void Rent(IMovie movie)
{
    var price = movie.Price();
    movie.MarkReserved();
}

public interface IMovie { }

public class Oldie : IMovie
{
    private decimal _oldieRate = 0.8;

    public decimal Price()
    {
        return MainData.RentPrice * _oldieRate;
    }
    public decimal MarkReserved()
    {
        _oldiesDb.MarkReserved(this, true);
    }
}


public class Blockbuster : IMovie
{
    private decimal _blockbusterRate = 1.2;

    public decimal Price()
    {
        return MainData.RentPrice * _blockbusterRate ;
    }
    public decimal MarkReserved()
    {
        _regularDb.MarkReserved(this, true);
    }
}
这就是为什么接口很有用的例子,但不是很好的代码设计例子

根据经验,您应该编写方法,以便它们需要的输入最少,并且它们的输出在调用时为其他人提供尽可能多的信息。例如,请查看以下签名:

public List<Entity> Filter(IEnumerable<Entity> baseCollection){ ... }
此方法只请求IEnumerable,因此它可以采用不同的集合类型,如List、Entity[]或某些工具返回的自定义类型。但您返回列表,这样就不会立即将调用者限制为仅可枚举元素。例如,她可以立即在返回值上使用Linq


还有更多的好处,比如在单元测试中,您可以创建模拟对象,并告诉它们在与其余代码交互期间如何行为。尽管如此,您现在可以使用带有虚拟方法的类来实现这一点。

在您的具体示例中,我想说这并不重要,因为您正在使用new并创建一个具体类型。当你开始使用它时,它开始变得更有用

更有用的场景看起来像t 他说:

public SomeResultType DoSomething(ISomeType obj)
{
    //to something with obj
    // return someResultType
}

可以使用任何类型调用上述函数,只要它实现了ISomeType。但在您使用new关键字的示例中,我将使用var。由于它继承了该类型,您仍然可以将其视为它实现的类型。

在您的具体示例中,我想说,这并不重要,因为您使用new并创建了一个具体类型。当你开始使用它时,它开始变得更有用

更有用的场景如下所示:

public SomeResultType DoSomething(ISomeType obj)
{
    //to something with obj
    // return someResultType
}

可以使用任何类型调用上述函数,只要它实现了ISomeType。但在您使用new关键字的示例中,我将使用var。由于它继承了该类型,您仍然可以将其视为它实现的类型。

假设IMyInterface具有Draw方法,现在所有派生类都必须实现Draw方法。如果您有一个带有RenderIMyInterface shape方法的类引擎,则无论形状是什么,都只需调用Draw方法。每一个形状都能随心所欲地画出来。
你可以看看设计模式,你可以看到界面的魔力

假设IMyInterface有Draw方法,现在所有派生类都必须实现Draw方法。如果您有一个带有RenderIMyInterface shape方法的类引擎,则无论形状是什么,都只需调用Draw方法。每一个形状都能随心所欲地画出来。
你可以看看设计模式,你可以看到界面的魔力

阅读:为了直观地理解它,在声明后的varInt后面写一个点,Intellisense将显示两者之间的差异。阅读:为了直观地理解它,声明后在varInt后面写一个点,Intellisense将显示两者之间的差异。如果使用抽象类或带有虚拟方法的类,也可以实现上述所有优势。类比接口更灵活。所以我看不出有任何理由在类上使用接口,除非需要多重继承。除了你的评论部分,这是你提问的核心。正如您所知,.NET中不存在多重继承,如果一个类已经继承了一个继承,您将无法向它添加另一个抽象。另外,IEnumerable示例是您在现实世界中经常看到的一个非常具体的示例。如何用抽象类而不是IList映射NHibernate中的集合?除非必要,否则您不能将类的实现强加给其他人,而且通常您甚至不需要抽象类,因为您不需要共享代码。如果我们使用抽象类或带有虚拟方法的类,也可以实现上述所有优势。类比接口更灵活。所以我看不出有任何理由在类上使用接口,除非需要多重继承。除了你的评论部分,这是你提问的核心。正如您所知,.NET中不存在多重继承,如果一个类已经继承了一个继承,您将无法向它添加另一个抽象。另外,IEnumerable示例是您在现实世界中经常看到的一个非常具体的示例。如何用抽象类而不是IList映射NHibernate中的集合?除非必要,否则您不能将类的实现强加给其他人,而且通常您甚至不需要抽象类,因为您不需要共享代码。