[英]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
,您就不会在意该方法是否实际上返回List
, Dictionary
或其他任何东西。 但是,例如,如果您强迫编译器返回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.