首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >您需要协变量返回类型做什么?

您需要协变量返回类型做什么?
EN

Software Engineering用户
提问于 2018-04-05 09:01:15
回答 3查看 3.5K关注 0票数 8

这篇文章中,编写的是在C# 8.0中包含新的不变返回类型特性,因为社区在很长一段时间内都在要求这个特性。

有谁能用实例来解释为什么和什么时候需要这个特性吗?

EN

回答 3

Software Engineering用户

回答已采纳

发布于 2018-04-05 09:31:41

首先,值得注意的是,这篇文章很可能是错误的。目前有一长串正式指定用于C# 8.0的特性,但协变量返回类型不是其中之一。这个特性计划在X.0 (它需要出现在一个主要版本中),所以它可能出现在8.0 (但这是难以置信的不可能),更有可能将在9.0或10.0等。

至于功能的用途是什么,读一读三年前的罗斯林原版。它可以在派生类型的方法中缩小返回类型,例如工厂接口的实现可以指定它返回一个具体类型,而不是一个接口。

例如,使用泛型,我们可以执行如下操作:

代码语言:javascript
复制
public interface IFactory<T>
{
    T Create();
}

public class Foo{}

public class FooFactory : IFactory<Foo>
{
    public Foo Create() => null;
}

但是,如果IFactory使用更多的接口来进行抽象,而不是泛型,那么类似的代码目前是不可能的:

代码语言:javascript
复制
public interface IFoo {}

public interface IFactory
{
    IFoo Create();
}

public class Foo : IFoo {}

public class FooFactory : IFactory
{
    public Foo Create() => null; // Compiler complains at Foo; wants IFoo
}

使用协变返回类型,这种代码将成为合法的。

票数 9
EN

Software Engineering用户

发布于 2018-04-05 09:55:31

协变返回类型意味着方法覆盖可以指定比基本方法更特定的返回类型。例如:

代码语言:javascript
复制
class WebRequest {
    virtual WebRequest Create() { ... }
}

class HttpWebRequest : WebRequest {
    override HttpWebRequest Create() { ... }
}

目前(没有协变量返回类型) overriden方法必须指定完全相同的返回类型WebRequest,您必须手动将返回值转换为HttpWebRequest,这很难看。

票数 3
EN

Software Engineering用户

发布于 2018-04-05 12:13:36

(事先道歉,C#有点生疏)

正如在其他答案中提到的,不变返回类型的主要特性是,您可以使用返回更特定返回类型的函数覆盖虚拟函数。

例如:

代码语言:javascript
复制
public class Foo
{
    virtual public Foo getCopy(); { //Create a copy of this Foo and return it }
}

到目前为止,getCopy()方法返回在其上调用的Foo的副本。让我们添加一个从Foo继承的类。

代码语言:javascript
复制
public class Bar : Foo
{
    override public Foo getCopy(); { //Create a copy of this Bar and return it as a Foo }
}

注意,如果没有协变量返回类型,我们需要声明返回一个Foo (正式)而不是Bar (尽管我们实际上返回了一个Bar)。在编写以下代码之前,这可能不会那么糟糕。

代码语言:javascript
复制
//Copying things
Foo myFoo;
Foo myOtherFoo = myFoo.getCopy();

Bar myBar;
Bar myOtherBar = myBar.getCopy(); //Compiler error - getCopy() returns a Foo

尽管您知道myBar是一个Bar,并且您(实际上)从myBars的getCopy()中获得了一个Bar,但是您需要转换返回值才能编译它。更糟的是,它是细菌的潜在来源.

代码语言:javascript
复制
public class Baz : Foo
{
    override public Foo getCopy(); { //Create a copy of this Baz and return it as a Foo }
}

//Copying more things
Foo myFoo;
Foo myOtherFoo = myFoo.getCopy();

Bar myBar;
Bar myOtherBar = myBar.getCopy() as Bar;

Baz myBaz;
Baz myOtherBaz = myBar.getCopy() as Baz; //Whoops

注意到错误了吗?如果没有协变量返回值,您可能只会在运行时(当程序崩溃时)注意到,编译器可以在编译时告诉您:不,这不能工作。

总之:协变量返回值允许您编写更短、更精确和更安全的代码。

票数 3
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/368872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档