正如您在下面的代码中看到的,我已将Action<>对象声明为变量.
有人请让我知道为什么这个动作方法委托表现得像一个静态方法?
为什么它会true在以下代码中返回?
public static void Main(string[] args)
{
Action<string> actionMethod = s => { Console.WriteLine("My Name is " + s); };
Console.WriteLine(actionMethod.Method.IsStatic);
Console.Read();
}
Run Code Online (Sandbox Code Playgroud)

此代码在标记的行上引发异常:
using System;
using System.Linq.Expressions;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Action<int, int> a = (x, y) => Console.WriteLine(x + y);
ParameterExpression p1 = Expression.Parameter(typeof(int), "p1");
ParameterExpression p2 = Expression.Parameter(typeof(int), "p2");
// Here is the exception ArgumentNullException.
MethodCallExpression call = Expression.Call(a.Method, p1, p2);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我已经在VS2013(就像魅力)和VS2015社区(抛出异常)中测试了这段代码.
我跟着.Net参考源,这导致我有一些代码条件,检查是否提供了方法IsStatic.
在我的例子中,我传递的方法(a.Method)在VS2013中是静态的,并且由于某种原因在VS2015中是非静态的(实例).如果没有,它会抛出,告诉我我没有提供Instance论据.
为什么会这样?如何避免这种情况,以便Expression.Call在新的Visual Studio中重新开始工作?
我昨天在Visual Studio 2015中打开了我们的解决方案,我们的一些单元测试(在Visual Studio 2013中运行正常)开始失败.Digger更深入我发现这是因为召集GetTypes()一个程序集返回了不同的结果.我已经能够创建一个非常简单的测试用例来说明它.
在Visual Studio 2013和2015中,我使用.NET Framework 4.5.2创建了一个新的控制台应用程序.我在以下两个项目中都添加了以下代码.
class Program
{
static void Main(string[] args)
{
var types = typeof(Program).Assembly.GetTypes()
.Where(t => !t.IsAbstract && t.IsClass);
foreach (var type in types)
{
Console.WriteLine(type.FullName);
}
Console.ReadKey();
}
}
Run Code Online (Sandbox Code Playgroud)
当我在Visual Studio 2013中运行时,我得到以下输出(如预期的那样).
VS2013Example.Program
当我在Visual Studio 2015中运行时,我得到以下输出(不是预期的).
VS2015Example.Program
VS2015Example.Program + <>Ç
那是什么VS2015Example.Program+<>c类型的?原来它是.Where()方法中的lambda .是的,这是正确的,不知何故,本地lambda作为一种类型暴露.如果我.Where()在VS2015中注释掉,那么我就不再获得第二行了.
我已经使用Beyond Compare来比较两个.csproj文件,但唯一的区别是VS版本号,项目GUID,默认命名空间和程序集的名称,VS2015有一个对System.Net.Http的引用, VS2013一个没有.
有没有人见过这个?
有没有人解释为什么局部变量将在程序集级别作为类型公开?
c# compiler-construction roslyn visual-studio-2013 visual-studio-2015
我正在玩,delegates并注意到当我创建一个Func<int,int,int>类似下面的例子时:
Func<int, int, int> func1 = (x, y) => x * y;
Run Code Online (Sandbox Code Playgroud)
编译器生成的方法的签名不是我所期望的:

正如您所看到的,它需要一个对象作为它的第一个参数.但是当有一个关闭时:
int z = 10;
Func<int, int, int> func1 = (x, y) => x * y * z;
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作:

这是带有额外参数的方法的IL代码:
.method private hidebysig static int32 '<Main>b__0'(object A_0,
int32 x,
int32 y) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 2
.locals init ([0] int32 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: mul …Run Code Online (Sandbox Code Playgroud) 我希望有人可以识别出导致下面程序行为发生变化的语言特性(或bug).如果提供给Orchard :: Go的委托不是静态的,则会从更大的场景中重现它,该场景旨在记录消息.
using System;
namespace Sample
{
public static class Program
{
public static void Main()
{
new Apple();
}
}
public sealed class Apple
{
public Apple()
{
Orchard.Go(() => { });
}
}
internal static class Orchard
{
public static void Go(Action action)
{
Console.WriteLine(action.Method.IsStatic);
}
}
}
Run Code Online (Sandbox Code Playgroud)
场景是:
我很惊讶这两个委托(fn1和fn2)之间会有任何运行时差异:
static int SomeStaticMethod(int x) { return x; }
// fn1.Target == null in this case
Func<int, int> fn1 = SomeStaticMethod;
// fn2.Target != null in this case
Func<int, int> fn2 = x => x;
Run Code Online (Sandbox Code Playgroud)
但显然第二个lambda被视为实例方法,因为它的Target属性是非null.在我切换到Visual Studio 2015之前,它的处理方式不同(在VS2012中,我很确定它被视为静态方法).
是否有理由将没有闭包的lambda视为C#中的闭合委托(即实例方法)?我想也许这是调试器添加一些东西,但它也发生在发布版本中.
(澄清)
关键是,我有一个这样的方法,它创建了一个通用委托,用于快速从枚举转换为int(无需装箱):
private static Func<int, TEnum> CreateIntToEnumDelegate()
{
Func<int, int> lambda = x => x;
return Delegate.CreateDelegate(typeof(Func<int, TEnum>), lambda.Method)
as Func<int, TEnum>;
}
Run Code Online (Sandbox Code Playgroud)
它不再适用于Roslyn,因为"实例"lambda与委托签名不兼容.所以我不得不使用一种static方法,没什么大不了的.
但令我担心的是,这在编译期间无法捕获.这个帖子描述了类似的问题,顺便说一句,现在我搜索了"Roslyn代表".
鉴于以下控制台程序:
class Program
{
private static string _value;
static void Main(string[] args)
{
var t = new Action(() => _value = "foo");
Console.Out.WriteLine("t.Method.IsStatic: {0}", t.Method.IsStatic);
}
}
Run Code Online (Sandbox Code Playgroud)
当使用VS 2013针对.Net 4.5.2编译时,它将打印出来
t.Method.IsStatic: true
Run Code Online (Sandbox Code Playgroud)
当使用VS 2015针对.Net 4.5.2编译时,它将打印出来
t.Method.IsStatic: false
Run Code Online (Sandbox Code Playgroud)
从这个问题,我有点理解发生了什么,但我很困惑为什么VS的版本之间的行为发生了变化.根据我的理解,2013年的输出是正确的.