如何在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>
多次输入,让编译器推断其余的吗?
答案 0 :(得分:4)
如果我理解正确你的意思是这样的话:
List<int> MyIntList()
{
var result = new List<int>();
return result;
}
var
只是实际类型List<int>
的占位符或您分配给它的任何内容。与C#中的JavaScript相比,关键字与强类型相关,因此您可以像处理任何其他类型一样处理它,它会自动列出适合该类型的正确成员。
编辑:回答为什么你不能做你想做的事情:方法签名经常声明返回一个界面,但实际的类型根本不重要。通常,如果方法实际返回List
,Dictionary
或其他任何内容,只要它实现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的行为。有懒惰,然后放弃你的责任。