考虑以下代码:
using System;
#nullable enable
namespace Demo
{
public sealed class TestClass
{
public string Test()
{
bool isNull = _test == null;
if (isNull)
return "";
else
return _test; // !!!
}
readonly string _test = "";
}
}
Run Code Online (Sandbox Code Playgroud)
当我构建它时,标有的行!!!给出了编译器警告:warning CS8603: Possible null reference return.。
我觉得这有点令人困惑,因为它_test是只读的并且初始化为非空。
如果我将代码更改为以下内容,警告就会消失:
public string Test()
{
// bool isNull = _test == null;
if (_test == null)
return "";
else
return _test;
}
Run Code Online (Sandbox Code Playgroud)
谁能解释这种行为?
在分析我们的一个应用程序时,我们在一些代码中发现了一个神秘的减速,我们正在调用Enumerable.Single(source, predicate)一个大型集合,它有多个项目与集合开头附近的谓词相匹配.
调查显示,执行情况Enumerable.Single()如下:
public static TSource Single<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
TSource result = default(TSource);
long count = 0;
// Note how this always iterates through ALL the elements:
foreach (TSource element in source) {
if (predicate(element)) {
result = element;
checked { count++; }
}
}
switch (count) {
case 0: throw Error.NoMatch();
case 1: return result;
}
throw Error.MoreThanOneMatch();
}
Run Code Online (Sandbox Code Playgroud)
该实现将遍历序列的每个元素,即使多个元素已经与谓词匹配.
以下实现似乎会产生相同的结果:
public static TSource Single<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) …Run Code Online (Sandbox Code Playgroud) 在Visual Studio 2013的起始页上,有一个标题为"公告"的部分.
在该部分下面说:
及时了解有关Visual Studio的公告.要查看公告,请启用动态内容.
我的问题很简单:我在哪里启用"动态内容"?
还有一个名为"产品视频"的部分.在它下面是以下消息:
我们有很多精彩的内容可以向您展示,但我们需要您的许可才能保持更新.
如果您启用"动态内容",这也会启用吗?或者我需要启用另一个设置吗?
我原本以为为实现的空集合执行以下代码IEnumerable<T>会抛出异常:
var enumerator = collection.GetEnumerator();
enumerator.MoveNext();
var type = enumerator.Current.GetType(); // Surely should throw?
Run Code Online (Sandbox Code Playgroud)
因为集合是空的,所以访问IEnumerator.Current无效,我本来期望一个例外.但是,没有例外List<T>.
这是允许的文档IEnumerator<T>.Current,其中指出Current在以下任何条件下未定义:
(我假设"未能抛出异常"可归类为"未定义行为"......)
但是,如果你做同样的事情,但使用一个IEnumerable,你会得到一个例外.此行为由文档IEnumerator.Current指定,其中指出:
我的问题是:为什么会有这种差异?我不知道有一个很好的技术原因吗?
这意味着看起来相同的代码可以表现得非常不同,具体取决于它是否正在使用,IEnumerable<T>或者IEnumerable如下面的程序所示(注意代码内部showElementType1()和showElementType1()相同):
using System;
using System.Collections;
using System.Collections.Generic;
namespace ConsoleApplication2
{
class Program
{
public static void Main()
{
var list = new List<int>();
showElementType1(list); // Does not throw an exception.
showElementType2(list); // Throws …Run Code Online (Sandbox Code Playgroud) 如果struct包含DateTime字段,为什么LayoutKind.Sequential的工作方式不同?
请考虑以下代码(必须使用"unsafe"启用的编译器应用程序):
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication3
{
static class Program
{
static void Main()
{
Inner test = new Inner();
unsafe
{
Console.WriteLine("Address of struct = " + ((int)&test).ToString("X"));
Console.WriteLine("Address of First = " + ((int)&test.First).ToString("X"));
Console.WriteLine("Address of NotFirst = " + ((int)&test.NotFirst).ToString("X"));
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Inner
{
public byte First;
public double NotFirst;
public DateTime WTF;
}
}
Run Code Online (Sandbox Code Playgroud)
现在如果我运行上面的代码,我得到类似于以下的输出:
struct = 40F2CC的
地址First = 40F2D4的
地址NotFirst的地址= 40F2CC
注意,First的地址与struct的地址不同; 然而,NotFirst的地址是一样的结构的地址.
现在注释掉结构中的"DateTime WTF"字段,然后再次运行它.这一次,我得到的输出类似于:
struct …
我已经看到了类似的问题,但它们涉及不同类型,所以我认为这是一个新问题.
请考虑以下代码:
public void Test(bool value)
{
// The following line provokes a compiler error:
// "Type of conditional expression cannot be determined because there is
// no implicit conversion between 'method group' and 'method group".
Func<bool> test = value ? F : F;
}
public bool F()
{
return false;
}
Run Code Online (Sandbox Code Playgroud)
现在,根据C#3.0标准,
?:运算符的第二个和第三个操作数控制条件表达式的类型.设X和Y是第二个和第三个操作数的类型.然后,
如果X和Y是相同的类型,那么这是条件的类型否则,如果从X到Y存在隐式转换(第6.1节),而不是从Y到X,则Y是条件表达式的类型.否则,如果从Y到X存在隐式转换(第6.1节),而不是从X到Y,则X是条件表达式的类型.否则,无法确定表达式类型,并发生编译时错误.
在我看来,在我的示例代码中,X和Y必须是相同的类型,因为它们是同一个实体Func.那为什么不编译呢?
我正在尝试使用Microsoft.Bcl.Async和代码分析,但是当我运行代码分析时,我得到一个或多个错误.
我正在使用Visual Studio 2012和Update 2.
这对我来说很容易重现:
.Net 4.References然后选择Manage NuGet Packages...Online并async在Search Online框中键入.Async for .Net Framework 4 ....点击Install并接受所有问题.Main()一行说:TaskEx.Delay(1000);和ausing System.Threading.Tasks;Enable Code Analysis on Build.我收到两个代码分析错误:
CA0052运行代码分析时出错CA0052:未选择任何目标.[错误和警告](全球)
CA0055运行代码分析CA0055时出错:无法加载ConsoleApplication2.exe.读取模块"ConsoleApplication2"时遇到以下错误:无法解析成员引用:[Microsoft.Threading.Tasks,Version = 1.0.12.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a] System.Threading.Tasks.TaskEx :: Delay.[错误和警告](全球)
我为其他测试程序得到了不同的代码分析错误.我试过的基本Windows窗体应用程序给了我:
CA0001错误运行代码分析CA0001:读取模块"AsyncForNet4"时遇到以下错误:无法解析成员引用:[Microsoft.Threading.Tasks,Version = 1.0.12.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a] System.Threading. Tasks.TaskEx ::延迟.[错误和警告](全球)
两个问题:
[编辑]
感谢@VilleKrumlinde,我修复了一个错误,我在尝试避免代码分析警告时不小心引入了这个错误.我不小心打开了"重叠"文件处理,它不断重置文件长度.现在已修复,您可以FastWrite()多次为同一个流调用而不会出现问题.
[结束编辑]
概观
我正在做一些时序测试,以比较两种不同的方式将结构数组写入磁盘.我相信人们认为,与其他事物相比,I/O成本是如此之高,以至于不值得花太多时间优化其他事情.
但是,我的时间测试似乎表明不是这样.要么我犯了一个错误(这是完全可能的),要么我的优化确实非常重要.
历史
首先是一些历史记录:此FastWrite()方法最初是在几年前编写的,用于支持将结构写入遗留C++程序所使用的文件,我们仍然将其用于此目的.(还有一个相应的FastRead()方法.)它的编写主要是为了更容易将blittable结构数组写入文件,其速度是次要问题.
不止一个人告诉我,这样的优化并不比使用a更快BinaryWriter,所以我终于咬了一口子并进行了一些时序测试.结果让我感到惊讶......
这似乎是我的FastWrite()方法是30 -比同等使用快50倍BinaryWriter.这看起来很荒谬,所以我在这里发布我的代码,看看是否有人能找到错误.
系统规范
结果
我的结果是:
SlowWrite() took 00:00:02.0747141
FastWrite() took 00:00:00.0318139
SlowWrite() took 00:00:01.9205158
FastWrite() took 00:00:00.0327242
SlowWrite() took 00:00:01.9289878
FastWrite() took 00:00:00.0321100
SlowWrite() took 00:00:01.9374454
FastWrite() took 00:00:00.0316074
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这似乎表明FastWrite()该运行速度提高了50倍.
这是我的测试代码.运行测试后,我做了这两个文件的二进制比较来验证它们确实是相同的(即FastWrite()和SlowWrite()生产相同的文件).
看看你能做些什么.:)
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using …Run Code Online (Sandbox Code Playgroud) 我希望能够将新的 C#11required修饰符与 .NET Framework 4.8 和 .Net Standard 2.0 一起使用。
我使用的是 Visual Studio 2022 版本 17.4。这可能吗?
执行异步I/O的旧.Net方式FileStream是使用FileStream.BeginRead()和FileStream.EndRead().
状态的MSDN文档FileStream.BeginRead():
FileStream提供两种不同的操作模式:同步I/O和异步I/O. 虽然可以使用其中任何一种,但底层操作系统资源可能仅允许以这些模式之一进行访问.
默认情况下,FileStream会同步打开操作系统句柄.在Windows中,这会降低异步方法的速度.如果使用异步方法,请使用FileStream(String,FileMode,FileAccess,FileShare,Int32,Boolean)构造函数.
在.Net 4.5x对执行异步I/O的方式FileStream是使用Stream.ReadAsync().
MSDN文档FileStream.ReadAsync()直接链接到文档的链接Stream.ReadAsync().本文档未提及在异步模式下打开文件的任何需要; 实际上,文档中的示例代码显然没有这样做.
因此,我假设在使用时File.ReadAsync()不需要以异步模式打开文件.
这个假设是否正确?
[编辑]
我刚刚发现了一篇关于使用Async for File Access的MSDN文章.
这表明:
本主题中的示例使用FileStream类,该类具有导致在操作系统级别发生异步I/O的选项.通过使用此选项,您可以避免在许多情况下阻止ThreadPool线程.
要启用此选项,请在构造函数调用中指定useAsync = true或options = FileOptions.Asynchronous参数.
所以,现在我在想,我应该可以打开该文件在异步模式......如果是这样,这是有点遗憾的是,在文档中提供的示例代码ReadAsync()并不能打开该文件异步!
c# ×9
filestream ×2
.net ×1
.net-4.0 ×1
async-await ×1
beginread ×1
datetime ×1
fxcop ×1
ienumerable ×1
linq ×1
marshalling ×1
optimization ×1
structlayout ×1