小编Joe*_*nta的帖子

在结构方法中将"this"存储在局部变量中有什么好处?

我今天正在浏览.NET Core源代码树,并在以下模式中运行System.Collections.Immutable.ImmutableArray<T>:

T IList<T>.this[int index]
{
    get
    {
        var self = this;
        self.ThrowInvalidOperationIfNotInitialized();
        return self[index];
    }
    set { throw new NotSupportedException(); }
}
Run Code Online (Sandbox Code Playgroud)

这种模式(存储this在局部变量中)似乎始终在此文件中应用,this否则将在同一方法中多次引用,但在仅引用一次时则不会.所以我开始思考这样做的相对优势是什么; 在我看来,优势可能与性能有关,所以我走了这条路线更远......也许我忽略了别的东西.

为" 本地存储"模式发出的CILthis似乎看起来像a ldarg.0,然后ldobj UnderlyingType,stloc.0以便后来的引用来自ldloc.0而不是ldarg.0像只使用this多次一样.

对于C#-to-CIL转换或者JITter寻找机会为我们优化这一点可能ldarg.0要慢得多ldloc.0,但是不够,这样在C#代码中随时编写这种奇怪的模式更有意义否则我们会ldarg.0在struct实例方法中发出两条指令?

更新:或者,你知道,我可以查看该文件顶部的注释,它可以准确地解释发生了什么......

.net c#

33
推荐指数
2
解决办法
839
查看次数

考虑到目标之间的实现差异,如何正确地对具有多个目标框架的.NET项目进行单元测试?

考虑一个针对以下框架的.NET类库:

  • .NET Framework 2.0
  • .NET Framework 4.6
  • .NET Standard 1.0
  • .NET标准1.3
  • .NET Portable Profile336

让我们不要立即担心为什么这是目标框架的确切列表.

假设所有目标框架中的外部API是相同的,每个单独的目标框架都有一些该框架独有的代码,我如何正确编写涵盖所有目标框架代码的单元测试?

我正在运行Visual Studio 2017社区.

我已经在GitHub上制作了一个随时可用的最小样本,我到目前为止发现的可能是我现在能做的最好的:https://github.com/airbreather/MultiTargetDemo,但这不是感觉这是正确的做法.一些缺陷:

  • 需要为每个目标框架提供单独的.csproj文件,其中包含大量复制粘贴.
  • 使用一个没有很好记录的*属性调用ReferringTargetFrameworkForProjectReferences.
    • *这有点轻描淡写......此刻谷歌搜索,除了微软的SDK之外没有任何东西显示出来.
  • 似乎没有与.NET标准填充程序一起正常工作(.NET Standard 1.3在运行时尝试查找System.IO.FileSystem).(编辑:想通了,这是corefx问题#16322,它有一些尴尬的解决方法).

上面链接的库只有一个公共类,其上只有一个公共实例方法.该方法在合同上有义务只返回32位整数值3,但它在每个目标上计算3一个实质上不同的方式.显然,实际用例围绕实现更多"有趣"的方法,但这足以进行对话.

此外,请注意该库中的测试类实际上使用了一些在所有目标平台上都不可用的东西:System.Threading.Tasks.Task<TResult>在.NET Framework 2.0上不可用...这可以作为测试本身可能的任何内容的代理.用于其自身目的,可能不一定在正在测​​试的目标框架中可用.

实际用例是NetTopologySuite,它已经针对多个完整框架平台和一些PCL; 有一个长达一年的问题,要求它使用.NET Core.我一直在努力尝试将这种情况发生在一个月左右,我终于遇到了这个问题.

我发现了另一个问题:使用.NET Core和xUnit同时针对几个框架的单元测试代码,这确实与此类似.出于以下几个原因,这是不同的:

  • 那个问题是使用VS2015时代的预览SDK工具(project.json).这个问题是指VS2017时代的非预览工具与漂亮的.csproj文件和所有.
  • 这个问题可以通过简单地针对测试项目本身进行多目标解决,每个框架由"测试对象"定位一个"测试"目标框架.似乎这个问题不能以类似的方式解决,特别是对于异常的Profile336目标.
    • 此外,鉴于完整的.NET Framework 4.6可以引用针对任何列出的五个目标框架的程序集,我不需要将基本测试类的实现限制为在任何可能的交叉点中可用的内容.为此选择的目标框架的抓包.
    • 我也尝试像上市合成的东西一劈TargetFrameworkstest1;test2;test3;test4;test5,然后迫使TargetFrameworkIdentifier+ TargetFrameworkVersion到.NETFramework + 4.6,但我并没有多少成功的(它试图抓住时失败xunit包).我还没有尝试 …

.net unit-testing .net-core visual-studio-2017 .net-standard

24
推荐指数
1
解决办法
4881
查看次数

确切地说,MemoryCache的内存限制是什么意思?

System.Runtime.Caching.MemoryCache是.NET Framework(版本4+)中的一个类,它使用字符串作为键来缓存内存中的对象.除了System.Collections.Generic.Dictionary <string,object>之外,这个类还有各种各样的铃声和口哨声,可以让你配置缓存增长到多少(绝对或相对术语),设置不同的过期策略不同的缓存项目,以及更多.

我的问题与记忆限制有关.MSDN上的所有文档似乎都没有令人满意地解释这一点,并且Reference Source上的代码相当不透明.很抱歉将所有这些都写成一个"问题",但我无法弄清楚如何将一些问题纳入他们自己的问题,因为他们只是对一个整体问题的不同观点:"你如何调和惯用的C# /.NET有一个通常有用的内存缓存的概念,它有可配置的内存限制几乎完全在托管代码中实现?"

  1. 密钥大小是否计入MemoryCache占用的空间?实习池中的键怎么样,每个键应该只添加对象引用的大小到缓存的大小?
  2. 在确定池中存储的对象的大小时,MemoryCache是​​否考虑的不仅仅是它存储的对象引用的大小? 我的意思是......它必须,对吗?否则,配置选项对于常见情况极具误导性......对于其余问题,我将假设它确实如此.
  3. 鉴于MemoryCache几乎肯定会考虑超过缓存中存储的值的对象引用的大小,它有多深?
    1. 如果我实现这样的事情,我会觉得困难的考虑单个对象的"子"成员的内存使用情况,也没有拉动"父"的参考性.
    2. 例如,想象一下游戏应用程序中的一个类,Player. Player有一些特定于玩家的状态被封装在一个public PlayerStateData PlayerState { get; }属性中,该属性封装了玩家正在看的方向,他们持有的链轮数等等,以及对整个游戏状态的引用public GameStateData GameState { get; },可以用来回到游戏(更大)状态来自只知道玩家的方法.
    3. MemoryCache是​​否考虑两者PlayerState以及GameState何时考虑缓存贡献的大小?
    4. 也许它更像是" 直接存储在缓存中的对象所占用的托管堆上的大小,以及通过这些对象的成员可以访问的所有东西"?
    5. GameState仅仅因为5个玩家被缓存而将大小的贡献大小乘以5 是愚蠢的......但是再一次,一个可能的实现可能就是这样,并且很难计算PlayerState而不计算GameState.
  4. 如果一个对象在MemoryCache中多次存储,那么每个条目是否分别计入限制?
  5. 与前一个相关,如果一个对象直接存储在MemoryCache中,而且间接存储在另一个对象的成员中,那么它们对内存限制有什么影响?
  6. 如果一个对象存储在MemoryCache中,但也被一些完全与MemoryCache断开连接的其他活动对象引用,哪些对象计入内存限制?如果它是一个对象数组,有些(但不是全部)有传入的外部引用呢?

我自己的研究使我SRef.cs,我放弃了在试图让后了解这里,后来导致这里.猜测所有这些问题的答案将围绕寻找和冥想最终填充存储在该句柄中的INT64的代码.

.net c# caching memorycache

6
推荐指数
1
解决办法
691
查看次数

如果数据未按给定偏移量对齐,为什么 BitConverter.ToInt32 一次读取一个字节?

很抱歉标题令人困惑,但我想不出更好的方法来解释它。

最近在浏览源码BitConverter时,发现了一段奇怪的代码:

public static unsafe int ToInt32(byte[] value, int startIndex)
{
    fixed (byte* pbyte = &value[startIndex])
    {
        if (startIndex % 4 == 0) // data is aligned 
            return *((int*)pbyte);
        else
        { 
            if (IsLittleEndian)
            {  
                return (*pbyte) | (*(pbyte + 1) << 8)  | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24); 
            } 
            else
            { 
                return (*pbyte << 24) | (*(pbyte + 1) << 16)  | (*(pbyte + 2) << 8) | (*(pbyte + 3)); …
Run Code Online (Sandbox Code Playgroud)

.net c# pointers unsafe memory-alignment

6
推荐指数
1
解决办法
282
查看次数

如何尝试创建文件,并返回一个指示是否已创建的值?

我正在寻找类似于这样的签名的东西:

static bool TryCreateFile(string path);
Run Code Online (Sandbox Code Playgroud)

这需要避免跨线程,进程甚至访问相同文件系统的其他机器的潜在竞争条件,而不要求当前用户拥有超出其所需的任何权限File.Create.目前,我有以下代码,我不是特别喜欢:

static bool TryCreateFile(string path)
{
    try
    {
        // If we were able to successfully create the file,
        // return true and close it.
        using (File.Open(path, FileMode.CreateNew))
        {
            return true;
        }
    }
    catch (IOException)
    {
        // We want to rethrow the exception if the File.Open call failed
        // for a reason other than that it already existed.
        if (!File.Exists(path))
        {
            throw;
        }
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

还有另一种方法可以做到这一点,我错过了吗?

这适用于以下帮助器方法,旨在为目录创建"下一个"顺序空文件并返回其路径,再次避免跨线程,进程甚至访问同一文件系统的其他计算机的潜在竞争条件.所以我想一个有效的解决方案可能涉及到不同的方法:

static string GetNextFileName(string directoryPath)
{ …
Run Code Online (Sandbox Code Playgroud)

.net c# windows file-io .net-4.0

5
推荐指数
1
解决办法
183
查看次数