自动创建方法类型

时间:2016-04-14 13:21:41

标签: c# dry

如何在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>多次输入,让编译器推断其余的吗?

4 个答案:

答案 0 :(得分:4)

如果我理解正确你的意思是这样的话:

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

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

编辑:回答为什么你不能做你想做的事情:方法签名经常声明返回一个界面,但实际的类型根本不重要。通常,如果方法实际返回ListDictionary或其他任何内容,只要它实现IEnumerable,您就不会关心。但是,如果您强制编译器返回List<int>而不是IEnumerable<int>,那么您将失去所有接口的优点,因为您总是推断出接口的实际类型。话虽如此,mthod的使用者甚至可以在返回的列表中添加或删除元素。如果您使用所提到的接口,则返回的是表示可以枚举的值列表的内容。

还要考虑这种情况:

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

在这种情况下,编译器应该推断出什么类型?该方法的签名是与外界的契约,它决定了你可以对结果做些什么。

答案 1 :(得分:4)

也许这就是:

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

但是,您需要将类型作为类型参数传递T

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

答案 2 :(得分:1)

您正在寻找类似

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

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

使用最新版本的C#(6.0)无法实现此目的

答案 3 :(得分: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()?让编译器代表您选择侵犯违反Principle of Least Astonishment的行为。有懒惰,然后放弃你的责任。