[英]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.