簡體   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