请考虑以下代码:
using System;
using System.Diagnostics;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
for (int trial = 0; trial < 4; ++trial)
{
sw.Restart();
loop1();
Console.WriteLine("loop1() took " + sw.Elapsed);
sw.Restart();
loop2();
Console.WriteLine("loop2() took " + sw.Elapsed);
sw.Restart();
loop3();
Console.WriteLine("loop3() took " + sw.Elapsed);
// Console.WriteLine(); // <-- Uncomment this and the timings change a LOT!
}
}
static void loop1()
{
bool done = false;
for (int i = 0; i …Run Code Online (Sandbox Code Playgroud) 考虑以下代码......
在我对Windows 7 x64 PC(Intel i7 3GHz)上的RELEASE(不是调试!)x86版本的测试中,我获得了以下结果:
CreateSequence() with new() took 00:00:00.9158071
CreateSequence() with creator() took 00:00:00.1383482
CreateSequence() with new() took 00:00:00.9198317
CreateSequence() with creator() took 00:00:00.1372920
CreateSequence() with new() took 00:00:00.9340462
CreateSequence() with creator() took 00:00:00.1447375
CreateSequence() with new() took 00:00:00.9344077
CreateSequence() with creator() took 00:00:00.1365162
Run Code Online (Sandbox Code Playgroud)
似乎使用Func <>来定义委托以创建新对象比直接调用"new T()"快6倍.
我觉得这有点出乎意料......我想这是因为Jitter完成了一些内联,但我认为它本来可以优化"新T()".
有没有人对此有解释?
也许我犯了一些错误.(我已经考虑了垃圾收集器可能产生的影响,但重新排列代码并添加GC.Collect()等不会显着改变结果).
无论如何,这是代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication6
{
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
int repeats …Run Code Online (Sandbox Code Playgroud) ManualResetEventSlim:立即调用.Set()后跟.Reset()不会释放任何等待的线程
(注意:这也适用于ManualResetEvent,而不仅仅是ManualResetEventSlim.)
我在发布和调试模式下都尝试了下面的代码.我在四核处理器上运行的Windows 7 64位上使用.Net 4运行32位版本.我是从Visual Studio 2012编译的(所以安装了.Net 4.5).
我在系统上运行时的输出是:
Waiting for 20 threads to start
Thread 1 started.
Thread 2 started.
Thread 3 started.
Thread 4 started.
Thread 0 started.
Thread 7 started.
Thread 6 started.
Thread 5 started.
Thread 8 started.
Thread 9 started.
Thread 10 started.
Thread 11 started.
Thread 12 started.
Thread 13 started.
Thread 14 started.
Thread 15 started.
Thread 16 started.
Thread 17 started.
Thread 18 started.
Thread …Run Code Online (Sandbox Code Playgroud) 请考虑以下Console App代码:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
DateTime date = new DateTime(2014, 01, 19);
Console.WriteLine("{0}", date); // Prints 19/01/2014
Debug.WriteLine("{0}", date); // Prints 01/19/2014
Debug.WriteLine(date); // Prints 19/01/2014
Run Code Online (Sandbox Code Playgroud)
如评论中所述,Console.WriteLine()打印19/01/2014时Debug.WriteLine()打印01/19/2014.
更糟糕的是 - Debug.WriteLine("{0}", date)给出不同的输出Debug.WriteLine(date)......
是否会Debug.WriteLine()忽略线程的文化设置?
有没有办法Debug.WriteLine()利用线程的文化设置?或者我必须使用String.Format()并将结果传递给Debug.WriteLine()?
(注意:我在Windows 8.1 64位,en-GB上使用Visual Studio 2013和.Net 4.51以及AnyCPU调试版本运行.)
输入: uint hex = 0xdeadbeef;
所需输出: string result = "{deadbeef}"
第一种方法:明确添加{和}; 这工作:
result = "{" + string.Format("{0:x}", hex) + "}"; // -> "{deadbeef}"
Run Code Online (Sandbox Code Playgroud)
使用转义大括号输出为十进制而不是十六进制:
result = string.Format("{{{0}}}", hex); // -> "{3735928559}"
Run Code Online (Sandbox Code Playgroud)
似乎很有希望,现在我们需要做的就是:x按照上面的第一种方法添加十六进制说明符:
result = string.Format("{{{0:x}}}", hex); // -> "{x}"
Run Code Online (Sandbox Code Playgroud)
哦,亲爱的,添加它':x已经使它输出"{x}"而不是"{deadbeef}"我想要的.
所以我的问题是:我必须通过显式添加{和}按照第一个示例来解决这个问题,或者有没有办法使用复合格式化并转义大括号?
另请注意,这也会影响字符串插值(毕竟)只是由编译器转换为调用string.Format().
(这可能是重复的问题,但到目前为止我一直无法找到重复...)
编辑
请考虑以下代码,这些代码会引发 CA2104: Do not declare read only mutable reference types.
public class Test
{
// This provokes CA2104: "Do not declare read only mutable reference types".
protected readonly ImmutableClass ImmutableMember;
}
public class ImmutableClass
{
}
Run Code Online (Sandbox Code Playgroud)
有没有人知道一种方法将一个类标记为不可变的方式会抑制警告CA2104?
我试着装饰MutableClass而[ImmutableObject(true)]没有成功的希望(因为表格编辑器使用的属性非常清楚),而且确实它不起作用.
我假设Code Analysis在确定是否发出CA2104时使用已知的不可变类型列表,因此我们不能使用相同的方法.
我想即使你可以将一个类标记为不可变,编译器也无法实际检查它是否为真,但至少它可能是一个有用的指标.
无论如何,我有什么属性可以忽略吗?如果没有,则必须进行抑制.
目前似乎没有替代方法可以做到这一点.
我找到了一个有趣的博客,来自Joe Duffy("Windows上的并发编程"一书的作者)关于这种事情.
他从"想象我们有一个ImmutableAttribute"开始....... :)
这很有意思 - 他遇到了编写一些新的FxCop规则来分析属于不可变的类型的麻烦.
我是比较时机与寻找true一个值List<bool>使用List.Contains()与那些手卷循环.
我看到其他人报道的结果不同.我已经在几个系统上尝试过它,在我尝试过的所有系统上,循环看起来要快2到3.5倍.这些系统的范围从运行XP.4的笔记本电脑到运行Windows 8和.Net 4.5的最新PC.
其他人报告的结果不同,即List.Contains()与循环速度大致相同或略快于循环.
这是我的测试代码.
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main()
{
int size = 10000000;
int count = 10;
List<bool> data = new List<bool>(size);
for (int i = 0; i < size; ++i)
data.Add(false);
var sw = new Stopwatch();
for (int trial = 0; trial < 5; ++trial)
{
sw.Restart();
for (int i = 0; i …Run Code Online (Sandbox Code Playgroud) (注意:此示例代码需要C#7.2或更高版本以及Nuget System.Memory包.)
我们假设我们有readonly struct如下:
public readonly struct Test
{
public Test(int value)
{
Value = value;
}
public int Value { get; }
}
Run Code Online (Sandbox Code Playgroud)
现在让我们把它放到一个数组中:
var array = new Test[] { new Test(1) };
Console.WriteLine(array[0].Value); // Prints 1
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.您无法编写代码来array[0].Value直接修改.
现在假设我们这样做:
array.AsSpan().AsBytes()[3] = 1;
Console.WriteLine(array[0].Value); // Prints 16777217
Run Code Online (Sandbox Code Playgroud)
所以现在我们已经修改Value了数组中readonly结构的组件.
这种行为是否正确?
在 Visual Studio 2022 和 .net 6.0 中,我们有了新CallerArgumentExpression属性,可以用来“捕获传递给方法的表达式,以便在诊断/测试 API 中提供更好的错误消息并减少击键次数”。
例如,我们可以编写一个类来检查方法参数是否为空,如下所示:
public static class Contract
{
public static T RequiresArgNotNull<T>(T? item, [CallerArgumentExpression("item")] string? expression = default, string? message = null)
where T : class
{
if (item == null)
throw new ArgumentNullException(
expression ?? "<unknown>",
message ?? (expression != null ? "Requires " + expression + " != null" : "RequiresArgNotNull() failed."));
return item;
}
}
Run Code Online (Sandbox Code Playgroud)
可以像这样使用:
using static ClassLibrary1.Contract; // To allow just putting …Run Code Online (Sandbox Code Playgroud) Console.ReadKey()在多线程程序中使用时,我遇到了一个奇怪的问题.
我的问题是:为什么会这样?这是一个错误,还是因为我在滥用Console?(请注意,根据文档,控制台应该是线程安全的.)
用代码解释这个是最容易的:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine("X"); // Also try with this line commented out.
Task.Factory.StartNew(test);
Console.ReadKey();
}
private static void test()
{
Console.WriteLine("Entering the test() function.");
Thread.Sleep(1000);
Console.WriteLine("Exiting the test() function.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果你运行它并且没有按键,你认为会打印出什么?
答案正是您所期望的:
X
Entering the test() function.
Exiting the test() function.
Run Code Online (Sandbox Code Playgroud)
现在注释掉Console.WriteLine("X")并再次运行它(不按键).我希望看到这个输出:
Entering the test() function. …Run Code Online (Sandbox Code Playgroud)