简体   繁体   English

自动创建方法类型

[英]Automatically creating type of method

How can I automatically initialize the type of a method in C#? 如何在C#中自动初始化方法的类型?

For instance, 例如,

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

I've basically created an instance of the return type, to return. 我基本上已经创建了返回类型的实例来返回。 Is there something in the C# language that infers the type to return, so that an instance doesn't have to be created within the method, such as: 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;
}

Simply put, can I prevent List<int> in the example from being typed more than once, and let the compiler infer the rest? 简而言之,我可以防止示例中的List<int>多次键入,然后让编译器推断其余部分吗?

If I understand you correctly you mean something like this: 如果我正确理解您的意思,则是这样的:

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

var is just a placeholder for the actual type List<int> or whatever you assign to it. var只是实际类型List<int>或您为其分配的任何内容的占位符。 In contrast to JavaScript in C# the keyword relate to a strong type so you can deal with it as with any other type, it automatically lists the correct members appropriate for that type. 与C#中的JavaScript相反,关键字与强类型相关,因此您可以像处理其他任何类型一样处理它,它会自动列出适合该类型的正确成员。

EDIT: To answer why you can´t do what you want: The method-signature often states that an interface is returned, however the actual type doesn´t matter at all. 编辑:回答为什么您不能做自己想做的事情:方法签名通常指出返回了一个接口,但是实际类型根本不重要。 Usually you won´t care if the method actually returns a List , a Dictionary or anything else as long as it implements IEnumerable for example. 通常,只要方法实现IEnumerable ,您就不会在意该方法是否实际上返回ListDictionary或其他任何东西。 However if you´d force the compiler to return a List<int> instead of an IEnumerable<int> for example you lose all the benfits of interfaces as you allways infer the actual type insteaf of the interface. 但是,例如,如果您强迫编译器返回List<int>而不是IEnumerable<int> ,则当您始终推断接口的实际类型为insteaf时,将会丢失接口的所有好处。 Having said this the consumer of the mthod could even add or remove elements from/to the list being returned. 话虽如此,方法的使用者甚至可以从返回的列表中添加元素或从中删除元素。 If you´d use the mentioned interface all you return is something that represents a list of values which can be enumerated. 如果您使用提到的接口,则返回的所有内容都代表可以枚举的值的列表。

Also consider this case: 还要考虑这种情况:

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

What type should the compiler infer in this case? 在这种情况下,编译器应推断什么类型? The signature of the method is a contract to the outside which determines which things you can do with the result. 该方法的签名是与外部的合同,它确定您可以对结果执行哪些操作。

Perhaps this: 也许这:

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

But then you will need to pass the type as typeparameter T : 但是然后您需要将类型作为typeparameter T传递:

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

You're looking for something like 您正在寻找类似的东西

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

Having the compiler infer the return value and replace auto with List<int> 让编译器推断返回值,并用List<int>替换auto

This is not possible with the latest version of C# (6.0) 最新版本的C#(6.0)无法实现

I can't give a precise answer as to whether the C# specification disallows it, but I can provide examples. 对于C#规范是否不允许它,我无法给出确切的答案,但是我可以提供示例。 First, what if you want a method to return an interface? 首先,如果要一种方法返回接口怎么办? In your examples you used List<int> but what if you changed it to IList<int> ? 在示例中,您使用了List<int>但是如果将其更改为IList<int>怎么办? Or consider this simplified example: 或者考虑以下简化示例:

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");
}

You cannot create an instance of an interface. 您不能创建接口的实例。 So this is wrong: 所以这是错误的:

public IFoo BadFooCreate() => new IFoo(); // won't compile

But this would work, though it begs the question of how the compiler know you want Foo1 to be the particular IFoo that is returned: 但这将起作用,尽管它引发了一个问题,即编译器如何知道您希望Foo1成为返回的特定IFoo:

public IFoo GoodFooCreate() => new Foo1(); // compiles okay

This works too: 这也适用:

public IFoo GoodFooCreate() => Foo2.Create(); // compiles okay

But since Foo2 has a private constructor, this would not work: 但是由于Foo2具有私有构造函数,因此无法使用:

public IFoo BadFoo2Create() => new Foo2(); // won't compile

Another set of examples revolve around abstract classes. 另一组示例围绕抽象类。 Consider: 考虑:

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";
}

This would be wrong because you can't create an instance of an abstract class: 这将是错误的,因为您无法创建抽象类的实例:

public Animal BadAnimalCreate() => new Animal(); // won't compile

But this works perfectly fine: 但这工作得很好:

public Animal GoodAnimalCreate() => new Dog(); // compiles okay

Although again if the compiler were to automatically create a type for a lazy programmer, how would the compiler know to use Dog() and not Cat()? 尽管如果编译器再次为懒惰的程序员自动创建类型,编译器又将如何使用Dog()而不是Cat()? Letting the compiler pick on your behalf encroaches on violating the Principle of Least Astonishment . 让编译器代表您选择违反了“最小惊讶原则” There's being lazy and then there's abdicating your responsibility. 有一个懒惰,然后放弃了你的责任。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM