繁体   English   中英

自动创建方法类型

[英]Automatically creating type of method

如何在C#中自动初始化方法的类型?

例如,

List<int> MyIntList()
{
    List<int> returnList = new List<int>();
    return returnList;
}

我基本上已经创建了返回类型的实例来返回。 C#语言中是否有某些东西可以推断出要返回的类型,所以不必在方法中创建实例,例如:

List<int> MyIntList()
{
    // invalid - "this" refers to the containing class,
    // but looking for something that refers to the containing method.
    this = new List<int>();
    return this;
}

简而言之,我可以防止示例中的List<int>多次键入,然后让编译器推断其余部分吗?

如果我正确理解您的意思,则是这样的:

List<int> MyIntList()
{
    var result = new List<int>();
    return result;
}

var只是实际类型List<int>或您为其分配的任何内容的占位符。 与C#中的JavaScript相反,关键字与强类型相关,因此您可以像处理其他任何类型一样处理它,它会自动列出适合该类型的正确成员。

编辑:回答为什么您不能做自己想做的事情:方法签名通常指出返回了一个接口,但是实际类型根本不重要。 通常,只要方法实现IEnumerable ,您就不会在意该方法是否实际上返回ListDictionary或其他任何东西。 但是,例如,如果您强迫编译器返回List<int>而不是IEnumerable<int> ,则当您始终推断接口的实际类型为insteaf时,将会丢失接口的所有好处。 话虽如此,方法的使用者甚至可以从返回的列表中添加元素或从中删除元素。 如果您使用提到的接口,则返回的所有内容都代表可以枚举的值的列表。

还要考虑这种情况:

List<int> MyIntList()
{
    if (anyCondition)
    {
        var result = new List<int>();
        return result;
    }
    else 
    {
        var result = new int[0];
        return result
    }
}

在这种情况下,编译器应推断什么类型? 该方法的签名是与外部的合同,它确定您可以对结果执行哪些操作。

也许这:

private static T GetSomething<T>() where T: new()
{
    return new T();
}

但是然后您需要将类型作为typeparameter T传递:

var x = GetSomething<List<int>>();

您正在寻找类似的东西

auto MyIntList()
{
    return new List<int>();
}

让编译器推断返回值,并用List<int>替换auto

最新版本的C#(6.0)无法实现

对于C#规范是否不允许它,我无法给出确切的答案,但是我可以提供示例。 首先,如果要一种方法返回接口怎么办? 在示例中,您使用了List<int>但是如果将其更改为IList<int>怎么办? 或者考虑以下简化示例:

public interface IFoo
{
    void Bar();
}
public class Foo1 : IFoo
{
    public Foo1() { }
    public void Bar() => Console.WriteLine("Foo1.Bar");
}
public class Foo2 : IFoo
{
    private Foo2() { }
    public static Foo2 Create => new Foo2();
    public void Bar() => Console.WriteLine("Foo2.Bar");
}

您不能创建接口的实例。 所以这是错误的:

public IFoo BadFooCreate() => new IFoo(); // won't compile

但这将起作用,尽管它引发了一个问题,即编译器如何知道您希望Foo1成为返回的特定IFoo:

public IFoo GoodFooCreate() => new Foo1(); // compiles okay

这也适用:

public IFoo GoodFooCreate() => Foo2.Create(); // compiles okay

但是由于Foo2具有私有构造函数,因此无法使用:

public IFoo BadFoo2Create() => new Foo2(); // won't compile

另一组示例围绕抽象类。 考虑:

public abstract class Animal
{
    public Animal() { }
    public virtual string Name => "Generic Animal";
    public abstract string Speak();
}
public class Dog : Animal
{
    public override string Name => "Dog";
    public override string Speak() => "Bark";
}
public class Cat : Animal
{
    public override string Name => "Cat";
    public override string Speak() => "Meow";
}

这将是错误的,因为您无法创建抽象类的实例:

public Animal BadAnimalCreate() => new Animal(); // won't compile

但这工作得很好:

public Animal GoodAnimalCreate() => new Dog(); // compiles okay

尽管如果编译器再次为懒惰的程序员自动创建类型,编译器又将如何使用Dog()而不是Cat()? 让编译器代表您选择违反了“最小惊讶原则” 有一个懒惰,然后放弃了你的责任。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM