自动创建方法类型
Automatically creating type of method
如何在 C# 中自动初始化方法的类型?
例如,
List<int> MyIntList()
{
List<int> returnList = new List<int>();
return returnList;
}
我基本上已经创建了一个 return 类型的实例,到 return。 C#语言中有没有把类型推断为return,从而不必在方法内创建实例,如:
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 相比,该关键字与强类型相关,因此您可以像处理任何其他类型一样处理它,它会自动列出适合该类型的正确成员。
编辑:回答为什么你不能做你想做的事:方法签名通常声明接口是 returned,但是实际类型根本不重要。通常你不会关心该方法是否实际上 return 是 List
、Dictionary
或其他任何东西,只要它实现了 IEnumerable
。但是,如果您强制编译器 return 一个 List<int>
而不是 IEnumerable<int>
例如,您将失去接口的所有好处,因为您总是推断接口的实际类型而不是接口。话虽如此,该方法的使用者甚至可以添加或删除元素 from/to 正在 returned 的列表。如果你要使用提到的接口,你 return 就是代表可以枚举的值列表的东西。
也考虑这个案例:
List<int> MyIntList()
{
if (anyCondition)
{
var result = new List<int>();
return result;
}
else
{
var result = new int[0];
return result
}
}
在这种情况下,编译器应该推断出什么类型?方法的签名是与外部的契约,它决定了您可以对结果执行哪些操作。
您正在寻找类似
的内容
auto MyIntList()
{
return new List<int>();
}
让编译器推断 return 值并将 auto
替换为 List<int>
最新版本的 C# (6.0) 无法做到这一点
也许是这样:
private static T GetSomething<T>() where T: new()
{
return new T();
}
但是你需要将类型作为类型参数传递 T
:
var x = GetSomething<List<int>>();
关于 C# 规范是否不允许,我无法给出准确的答案,但我可以提供示例。首先,如果你想要一个 return 接口的方法怎么办?在您的示例中,您使用了 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 成为 returned:
的特定 IFoo 的问题
public IFoo GoodFooCreate() => new Foo1(); // compiles okay
这也有效:
public IFoo GoodFooCreate() => Foo2.Create(); // compiles okay
但是因为 Foo2 有一个私有构造函数,所以这行不通:
public IFoo BadFoo2Create() => new Foo2(); // won't compile
另一组示例围绕抽象 classes。考虑:
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";
}
这是错误的,因为您不能创建抽象的实例 class:
public Animal BadAnimalCreate() => new Animal(); // won't compile
但这工作得很好:
public Animal GoodAnimalCreate() => new Dog(); // compiles okay
虽然如果编译器自动为懒惰的程序员创建类型,编译器怎么知道使用 Dog() 而不是 Cat()?让编译器代表您进行选择侵犯了 Principle of Least Astonishment。有懒惰,然后有放弃你的责任。
如何在 C# 中自动初始化方法的类型?
例如,
List<int> MyIntList()
{
List<int> returnList = new List<int>();
return returnList;
}
我基本上已经创建了一个 return 类型的实例,到 return。 C#语言中有没有把类型推断为return,从而不必在方法内创建实例,如:
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 相比,该关键字与强类型相关,因此您可以像处理任何其他类型一样处理它,它会自动列出适合该类型的正确成员。
编辑:回答为什么你不能做你想做的事:方法签名通常声明接口是 returned,但是实际类型根本不重要。通常你不会关心该方法是否实际上 return 是 List
、Dictionary
或其他任何东西,只要它实现了 IEnumerable
。但是,如果您强制编译器 return 一个 List<int>
而不是 IEnumerable<int>
例如,您将失去接口的所有好处,因为您总是推断接口的实际类型而不是接口。话虽如此,该方法的使用者甚至可以添加或删除元素 from/to 正在 returned 的列表。如果你要使用提到的接口,你 return 就是代表可以枚举的值列表的东西。
也考虑这个案例:
List<int> MyIntList()
{
if (anyCondition)
{
var result = new List<int>();
return result;
}
else
{
var result = new int[0];
return result
}
}
在这种情况下,编译器应该推断出什么类型?方法的签名是与外部的契约,它决定了您可以对结果执行哪些操作。
您正在寻找类似
的内容auto MyIntList()
{
return new List<int>();
}
让编译器推断 return 值并将 auto
替换为 List<int>
最新版本的 C# (6.0) 无法做到这一点
也许是这样:
private static T GetSomething<T>() where T: new()
{
return new T();
}
但是你需要将类型作为类型参数传递 T
:
var x = GetSomething<List<int>>();
关于 C# 规范是否不允许,我无法给出准确的答案,但我可以提供示例。首先,如果你想要一个 return 接口的方法怎么办?在您的示例中,您使用了 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 成为 returned:
的特定 IFoo 的问题public IFoo GoodFooCreate() => new Foo1(); // compiles okay
这也有效:
public IFoo GoodFooCreate() => Foo2.Create(); // compiles okay
但是因为 Foo2 有一个私有构造函数,所以这行不通:
public IFoo BadFoo2Create() => new Foo2(); // won't compile
另一组示例围绕抽象 classes。考虑:
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";
}
这是错误的,因为您不能创建抽象的实例 class:
public Animal BadAnimalCreate() => new Animal(); // won't compile
但这工作得很好:
public Animal GoodAnimalCreate() => new Dog(); // compiles okay
虽然如果编译器自动为懒惰的程序员创建类型,编译器怎么知道使用 Dog() 而不是 Cat()?让编译器代表您进行选择侵犯了 Principle of Least Astonishment。有懒惰,然后有放弃你的责任。