考虑以下代码:
public class Class1
{
public static int c;
~Class1()
{
c++;
}
}
public class Class2
{
public static void Main()
{
{
var c1=new Class1();
//c1=null; // If this line is not commented out, at the Console.WriteLine call, it prints 1.
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Class1.c); // prints 0
Console.Read();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,即使main方法中的变量c1超出范围并且在GC.Collect()调用时没有被任何其他对象进一步引用,为什么它没有在那里完成?
我遇到了以下段落:
在Visual Studio中编译代码时,IDE中的"调试与发布"设置对性能几乎没有差别......生成的代码几乎相同.C#编译器并没有真正进行任何优化.C#编译器只是吐出IL ...而在运行时它是执行所有优化的JITer.JITer确实具有调试/释放模式,这对性能产生巨大影响.但这并不能决定你是否运行项目的调试或发布配置,而是关闭是否附加了调试器."
有人可以指导我一篇能够证明这一点的微软文章吗?
谷歌搜索" C#debug vs release performance "主要返回结果,说" Debug有很多性能损失 "," 发布已经优化 "," 不要将调试部署到生产中 ".
让我们考虑一下这个非常简单的异步方法:
static async Task myMethodAsync()
{
await Task.Delay(500);
}
Run Code Online (Sandbox Code Playgroud)
当我用VS2013(前Roslyn编译器)编译它时,生成的状态机是一个结构.
private struct <myMethodAsync>d__0 : IAsyncStateMachine
{
...
void IAsyncStateMachine.MoveNext()
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
当我使用VS2015(Roslyn)编译它时生成的代码是这样的:
private sealed class <myMethodAsync>d__1 : IAsyncStateMachine
{
...
void IAsyncStateMachine.MoveNext()
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,Roslyn生成一个类(而不是结构).如果我没记错的话,旧编译器中的async/await支持的第一个实现(我认为是CTP2012)也生成了类,然后由于性能原因将其更改为struct.(在某些情况下,你可以完全避免拳击和堆分配......)(见这个)
有谁知道为什么罗斯林再次改变了这一点?(我对此没有任何问题,我知道这个改变是透明的,不会改变任何代码的行为,我只是好奇)
编辑:
来自@Damien_The_Unbeliever(以及源代码:))imho的答案解释了一切.描述的Roslyn行为仅适用于调试版本(由于注释中提到的CLR限制,这是必需的).在Release中它还生成一个结构(具有该...的所有好处).所以这似乎是一个非常聪明的解决方案,支持编辑和继续以及更好的生产性能.有趣的东西,感谢所有参与的人!
错误和异常程序行为的典型原因是什么只在发布编译模式中表现出来但在调试模式下不会发生?
出于好奇,我试图使用C#生成尾调用操作码.Fibinacci是一个简单的,所以我的c#示例如下所示:
private static void Main(string[] args)
{
Console.WriteLine(Fib(int.MaxValue, 0));
}
public static int Fib(int i, int acc)
{
if (i == 0)
{
return acc;
}
return Fib(i - 1, acc + i);
}
Run Code Online (Sandbox Code Playgroud)
如果我在发布中构建并在没有调试的情况下运行它,我就不会出现堆栈溢出.在没有优化的情况下调试或运行它,我确实得到了堆栈溢出,这意味着尾部调用在发布时具有优化功能(这是我的预期).
这个MSIL看起来像这样:
.method public hidebysig static int32 Fib(int32 i, int32 acc) cil managed
{
// Method Start RVA 0x205e
// Code Size 17 (0x11)
.maxstack 8
L_0000: ldarg.0
L_0001: brtrue.s L_0005
L_0003: ldarg.1
L_0004: ret
L_0005: ldarg.0
L_0006: ldc.i4.1
L_0007: sub
L_0008: ldarg.1
L_0009: ldarg.0
L_000a: …Run Code Online (Sandbox Code Playgroud) 在VS2010 Pro的构建设置面板中,有一个带有"优化代码"标签的CheckBox ......当然,我想检查一下......但是要非常谨慎,我问我的兄弟,并且他说它未经检查以进行调试,并且在C++中它可能会做一些破坏或破坏代码的事情......但他不了解C#.
所以我的问题是,我可以在此框中查看我的发布版本,而不必担心它会破坏我的代码吗?第二,如果它可以破解代码,何时以及为什么?欢迎解释链接.
我正在清理一些代码并删除了if不再需要的语句.但是,我意识到我忘了删除括号.这当然是有效的,只是创建了一个新的本地范围.现在这让我思考.在我多年的C#开发中,我从未遇到过使用它们的理由.事实上,我有点忘了我能做到.
定义本地范围有什么实际好处吗?我理解我可以在一个范围内定义变量,然后在不相关的范围(for,foreach等)中再次定义相同的变量,如下所示:
void SomeMethod()
{
{
int i = 20;
}
int i = 50; //Invalid due to i already being used above.
}
void SomeMethod2()
{
{
int i = 20;
}
{
int i = 50; //Valid due to scopes being unrelated.
}
{
string i = "ABCDEF";
}
}
Run Code Online (Sandbox Code Playgroud)
定义本地范围的真正意义何在?实际上是否可以获得任何类型的性能提升(或潜在的损失)?我知道你可以用C++做到这一点,并且是帮助你管理内存的一部分,但是因为这是.NET,真的会有好处吗?这只是语言的双重产品,让我们定义随机范围即使没有真正的好处吗?
在我的测试项目中,我有一些未在代码中分配的私有字段,但是被分配了反射.
编译时,我收到如下警告:
警告CS0649字段'CLASSNAME.FIELDNAME'永远不会被赋值,并且将始终具有其默认值null
我已经尝试添加<NoWarn>649</NoWarn>到xproj中的第一个PropertyGroup.但我仍然得到错误.
NoWarn在DNX中不起作用吗?或者我做错了什么?这个问题还有其他解决办法吗?
我在.NET中发现了这种奇怪的行为,甚至在通过C#再次查看CLR之后我仍然感到困惑.让我们假设我们有一个接口,一个方法和一个实现它的类:
interface IFoo
{
void Do();
}
class TheFoo : IFoo
{
public void Do()
{
//do nothing
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们只想实例化这个类并以两种方式多次调用这个Do()方法:使用具体的类变量和使用接口变量:
TheFoo foo1 = new TheFoo();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (long i = 0; i < 1000000000; i++)
foo1.Do();
stopwatch.Stop();
Console.Out.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds);
IFoo foo2 = foo1;
stopwatch = new Stopwatch();
stopwatch.Start();
for (long i = 0; i < 1000000000; i++)
foo2.Do();
stopwatch.Stop();
Console.Out.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds);
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是(至少对我而言)经过的时间差异大约为10%:
Elapsed time: …Run Code Online (Sandbox Code Playgroud) c# ×8
.net ×4
performance ×2
c++ ×1
cil ×1
clr ×1
debug-mode ×1
debugging ×1
dnx ×1
f# ×1
interface ×1
jit ×1
optimization ×1
recursion ×1
release ×1
release-mode ×1
roslyn ×1
scope ×1
settings ×1