为什么构造函数不支持类型推断,就像通用方法一样?
public class MyType<T>
{
private readonly T field;
public MyType(T value) { field = value; }
}
var obj = new MyType(42); // why can't type inference work out that I want a MyType<int>?
Run Code Online (Sandbox Code Playgroud)
虽然你可以用工厂类解决这个问题,
public class MyTypeFactory
{
public static MyType<T> Create<T>(T value)
{
return new MyType<T>(value);
}
}
var myObj = MyTypeFactory.Create(42);
Run Code Online (Sandbox Code Playgroud)
构造函数不支持类型推断是否存在实际或哲学原因?
为什么以下无法推断R:
static R Foo<R>(Func<Action<R>, R> call) { ... }
Run Code Online (Sandbox Code Playgroud)
虽然几乎是'相同',但作品:
static R Foo<R>(Func<Action, R> call) { ... }
Run Code Online (Sandbox Code Playgroud)
用法:
var i = Foo(ec => -1);
Run Code Online (Sandbox Code Playgroud)
第一个样本'必须'被编译的方式:
var i = Foo<int>(ec => -1);
Run Code Online (Sandbox Code Playgroud)
- 要么 -
var i = Foo((Action<int> ec) => -1);
Run Code Online (Sandbox Code Playgroud)
思考:从第二个片段可以看出,R已经由'lambda'的返回类型决定.为什么不能同样适用于第一个?即使使用ec(应该是另一个编译器提示),它也无法推断.
我最近一直在研究功能编程,并希望将一些概念带到我的C#世界.我正在尝试编写函数来创建服务(或任何你称之为的服务),而不是创建具有可注入依赖项的类.
我想方设法通过创建一个像这样的静态方法,用两个参数和一个返回参数来部分应用一个函数(与注入依赖项具有相同的效果):
// this makes a func with a single arg from a func with two
static Func<T2, TResult> PartiallyApply<T1, T2, TResult>(
Func<T1,T2, TResult> f,
T1 t1)
{
// use given t1 argument to create a new function
Func<T2, TResult> map = t2 => f(t1, t2);
return map;
}
Run Code Online (Sandbox Code Playgroud)
这工作,但我想传递一个静态方法,如下所示:
static string MakeName(string a, string b) => a + " " + b;
Run Code Online (Sandbox Code Playgroud)
当我尝试连接它时,我得到错误The type arguments for method 'Program.PartiallyApply<T1, T2, TResult>(Func<T1, T2, TResult>, T1)' cannot be inferred …
为什么不能Main推断出调用中以下代码示例的类型参数?
using System;
class Program
{
static void Main(string[] args)
{
Method(Action);
}
static void Action(int arg)
{
// ...
}
static void Method<T>(Action<T> action)
{
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
这给出以下错误消息:
错误CS0411:
Program.Method<T>(System.Action<T>)无法从用法推断出方法的类型参数.尝试显式指定类型参数.
我正在使用一个函数,它接受两个函数作为参数,并返回一个新的组合函数:
public static Action<T> Compose<T>(Action<T> first, Action second)
{
return new Action<T>(arg =>
{
first(arg);
second();
});
}
Run Code Online (Sandbox Code Playgroud)
我注意到编译器抱怨如果我没有指定T,当发送静态或成员函数(而不是实际Action<T>对象)时:
static void Main(string[] args)
{
// compiler error here
var composed = Compose(Test, () => Console.WriteLine(" world"));
composed("hello");
Console.ReadLine();
}
public static void Test(string arg)
{
Console.Write(arg);
}
Run Code Online (Sandbox Code Playgroud)
错误消息:
无法从用法中推断出方法'ConsoleTest.Program.Compose(System.Action,System.Action)'的参数.尝试显式指定类型参数.
我的问题:为什么不能在这里推断出类型论证?签名Test是在编译时知道的,不是吗?是否真的有一些功能可以代替Test,这会导致它的签名含糊不清?
附注:我知道我可以简单地发送new Action<string>(Test),而不是Test到Compose(在注意这个问题) -我的问题是"为什么",而不是"我怎样才能做到这一点."
为什么C#编译器不够智能在下列情况下推断类型?
假设我有一个像这样定义的静态成员函数:
static Func<X, Z> pipe<X, Y0, Z>(Func<X, Y0> f0, Func<Y0,Z> f1) => x => f1(f0(x));
Run Code Online (Sandbox Code Playgroud)
然后,我定义了几个要测试的函数:
static double _toDouble(int x) => (double)x;
static short _toShort(double x) => (short)x;
Run Code Online (Sandbox Code Playgroud)
然后,一个人想要
var f = pipe(_toDouble, _toShort);
Run Code Online (Sandbox Code Playgroud)
但遗憾的是,必须这样做
var f = pipe<int,double,short>(_toDouble, _toShort);
Run Code Online (Sandbox Code Playgroud)
我认为没有办法解决这个问题,但如果证明是错误的话会很好,我不明白为什么它不能推断出使用的类型.
编译器无法解决这种类型推理问题的根本原因是什么,并且可以做任何事情来使上述管道/组合"操作符"工作(具有强类型泛型,没有反射等)而没有明确提供类型参数?
如果没有那么这个管道功能(以及同一系列中的其他类似功能)是无用的并且增加了语法噪声而不是减少它.
我有这段简单的代码:
class Program
{
static void test<T1>(Action<T1> action) { }
static void test<T1, T2>(Action<T1, T2> action) { }
static void B(int a) { }
static void C(string a, int b) { }
static void Main(string[] args)
{
test(B);
test(C);
}
}
Run Code Online (Sandbox Code Playgroud)
由于两个错误而无法编译:
The type arguments for method 'Program.test<T1>(Action<T1>)' cannot be
inferred from the usage. Try specifying the type arguments explicitly.
The type arguments for method 'Program.test<T1>(Action<T1>)' cannot be
inferred from the usage. Try specifying the type arguments explicitly.
Run Code Online (Sandbox Code Playgroud)
当然,如果我明确指定类型参数,它将起作用。
test<int>(B); …