访问 C# 类中的变量是否会从内存中读取整个类?

2024-01-08

我对 C# 很陌生,有一个问题困扰了我一段时间。

当我学习 C# 时,我被告知类不应包含大量变量,因为这样读取变量(或从中调用方法)会很慢。

有人告诉我,当我访问 C# 类中的变量时,它会从内存中读取整个类以读取变量数据,但这对我来说听起来很奇怪且错误。

例如,如果我有这样的课程:

public class Test
{
    public int toAccess; // 32 bit
    private byte someValue; // 8 bit
    private short anotherValue; // 16 bit
} 

然后从 main 访问它:

public class MainClass
{
    private Test test;
    public MainClass(Test test)
    {
        this.test = test;
    }
    public static void Main(string[] args)
    {
        var main = new MainClass(new Test());
        Console.WriteLine(main.test.toAccess); // Would read all 56 bit of the class
    }
}

我的问题是:这真的是真的吗?访问变量时是否会读取整个类?


For classes,这实际上没有任何区别;你总是只处理一个引用和该引用的偏移量。传递参考是非常便宜的。

When it does开始重要的是structs。请注意,这不会影响调用类型上的方法- 通常这是基于引用的静态调用;但是当结构是一个参数对于方法来说,这很重要。

(编辑:实际上,在结构上调用方法时也很重要if你通过装箱操作来调用它们,因为盒子也是一个副本;这是避免盒装电话的一个重要原因!)

免责声明:你probably不应该经常使用结构。

对于结构体,该值占用那么多空间无论何时将其用作值,它可以是一个字段、堆栈上的局部变量、范围到方法等。这也意味着copying结构(例如,作为参数传递)可能会很昂贵。但如果我们举个例子:

struct MyBigStruct {
   // lots of fields here
}

void Foo() {
    MyBigStruct x = ...
    Bar(x);
}
void Bar(MyBigStruct s) {...}

然后当我们打电话时Bar(x), we copy堆栈上的结构。同样,每当本地用于存储时(假设它没有被编译器删除):

MyBigStruct x = ...
MyBigStruct asCopy = x;

但!我们可以通过传递一个来解决这些问题参考周围代替。在当前版本的 C# 中,最合适的做法是使用in, ref readonly, and readonly struct:

readonly struct MyBigStruct {
   // lots of readonly fields here
}
void Foo() {
    MyBigStruct x = ...
    Bar(x); // note that "in" is implicit when needed, unlike "ref" or "out"
    ref readonly MyBigStruct asRef = ref x;
}
void Bar(in MyBigStruct s) {...}

现在有zero实际副本。这里的所有内容都涉及对原始内容的引用x。事实确实如此readonly意味着运行时知道它可以信任in参数上的声明,而不需要值的防御性副本。

具有讽刺意味的是,也许:添加in参数上的修饰符可以介绍如果输入类型是 a 则复制struct未标记的readonly,因为编译器和运行时需要保证内部所做的更改Bar调用者将看不到。这些更改不必是显而易见的 - 如果类型是邪恶的,任何方法调用(包括属性获取器和一些运算符)都可以改变值。举个邪恶的例子:

struct Evil
{
    private int _count;
    public int Count => _count++;
}

编译器和运行时的工作是按可预测的方式工作even if你是邪恶的,因此它添加了结构的防御副本。与相同的代码readonly结构体上的修饰符不会编译.


你也可以做类似的事情in with ref如果类型不是readonly,但是你需要意识到如果Bar改变值(故意或作为副作用),这些变化将是可见的Foo.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

访问 C# 类中的变量是否会从内存中读取整个类? 的相关文章

随机推荐

  • WEB API Action Method 的返回类型应该是什么?

    我正在使用 NET Core 开发 ASP NET Web API 该Web API将主要由UI应用程序访问 UI将使用ASP NET Core MVC开发 但将来API也可能被其他应用程序访问 在我的 WEB API 中 所有方法都是异步
  • Socket.io 发出进度检查

    我使用 Socket io 来上传文件 它适用于以下架构 客户端 从输入读取文件并将其编码为 Base64 并压缩 客户端 发出 Socket io 事件 上传 包括压 缩文件作为数据片段 服务器 监听 上传 事件 解压缩并解码文件并保存
  • PDOException 找不到驱动程序

    我正在使用 symfony 当我在控制台中输入以下内容时 php app console doctrine schema create 我有接下来的错误 学说 DBAL 异常 DriverException 驱动程序出现异常 找不到驱动程序
  • 使用多个分隔符并保留每个分隔符有效地分割字符串?

    我需要使用每个字符来分割数据字符串string punctuation and string whitespace作为分隔符 此外 我需要将分隔符保留在输出列表中 位于它们在字符串中分隔的项目之间 例如 Now is the winter
  • 如何显示接口方法的所有实现实例?

    在我的项目中 使用了大量的接口类 我在阅读和理解代码时遇到困难 因为浏览代码的定义 通过选择方法名称并按 F12 或右键单击 转到定义 只会引导我进入界面 Visual Studio 2010 中是否有一种方法 内置或插件 可以列出接口方法
  • Vagrant:缺少文件 id_rsa

    我正在使用带有 homestead 的 Windows 并且尝试在命令行上输入 vagrant up 但出现此错误 C www Homestead scripts homestead rb 106 inread No such file o
  • 使用Qt4捕获多个屏幕桌面图像

    我正在用 C 在 Qt4 中编写屏幕捕获应用程序 我在双屏上调整时遇到问题 我无法使用第二个屏幕获取图像 我尝试了一个 C 应用程序 它将抓取一个图像中的所有桌面 我可以从那里提取每个屏幕桌面图像 这是c 代码 using System u
  • 链接 pthread 库问题

    我面临着一个解释和理解可能稍微复杂的问题 因为给出整个图片太大且困难 请原谅 考虑以下 Makefile all clients so simulator backup LD PRELOAD home Juggler client clie
  • Gradle 工具 api 获取任务输出

    借助 Gradle 工具 API 我成功获得了一些项目的任务列表GradleProject getTasks 这有点酷 我可以读取任务的名称 描述 组以及是否公开 我想知道是否有可能获得任务输出目录 特别是对于测试或代码覆盖率的内容 即生成
  • 服务器上的自动化 django 接收钩子:用“yes”响应collectstatic

    我正在使用 Github post recieve hook 来运行一个 bash 文件来提取我的两个存储库 bin sh cd public html repo static env i usr bin git pull origin m
  • 如何将 gradle 多项目存储库作为 git 子模块包含在另一个 gradle 项目中

    我正在尝试将 Gradle 多项目存储库作为 git 子模块导入到另一个 Gradle 项目中 这是多项目存储库的结构 MyLibrary lib api api config api repository lib impl impl co
  • Angular Dart 教程第 5 节 - 'self.injector$Injector'

    在 英雄之旅 教程的第 5 节中 main dart包含以下行 最终 InjectorFactory 注入器 self injector Injector 这是拼写错误吗 它在 VSCode 中向我发出警告 我遇到了同样的问题 因为它完成没
  • “存在(从...中选择 1)”这一做法从何而来?

    The 绝大多数人支持 https stackoverflow com questions 424212 performance of sql exists usage variants我个人认为以下说法没有区别 SELECT FROM t
  • MongoDB.service 失败,结果退出代码

    我无法使用命令 sudo systemctl start mongod 启动 mongoDB 我收到以下消息 mongod service MongoDB Database Server Loaded loaded lib systemd
  • Android 无尽列表内存管理

    我通过在 onScrollStateChanged 方法中将更多项目加载到数组列表来实现无限列表视图 如果我实现这个方案来获取超过 100 万个条目 我将向数组列表添加一百万个对象 这是内存密集型的 我可以使用哪些方案来实现高效的内存管理
  • 如何从用户控件调用方法到aspx页面?

    我想从用户控件调用一个方法到aspx页面 我正在尝试 但无法在 aspx 页面中调用该方法 Code 添加VisaUserControl ascx cs public event EventHandler UserControlButton
  • 顶级批处理模式下的 CPU 使用率

    我有一个让我生气的问题 我使用以下命令以批处理模式运行 top top b n 1 问题是我可以在批处理模式下运行 top 100 次 但 CPU 使用率永远不会超过原始值 内存使用量按预期变化 但 CPU 保持不变 如果我同时在不同的窗口
  • 使用 Transact-SQL 查找特定子字符串

    我需要从以下形式的字符串中提取特定的子字符串 foo abc bar def baz ghi 例如 我如何从该字符串中获取 bar 的值 您可以使用字符索引 http msdn microsoft com en us library ms1
  • 关系设计场景:限制子关系

    请考虑以下场景 宠物主人可能有多只猫 也可能有多只狗 有些狗与一些猫有亲缘关系 即它们打架 同一所有者的 以下关系设计不施加此限制 因为不同所有者的猫和狗可能是相关的 有没有办法通过关系设计来施加这种限制 您需要使用识别关系将所有者的 PK
  • 访问 C# 类中的变量是否会从内存中读取整个类?

    我对 C 很陌生 有一个问题困扰了我一段时间 当我学习 C 时 我被告知类不应包含大量变量 因为这样读取变量 或从中调用方法 会很慢 有人告诉我 当我访问 C 类中的变量时 它会从内存中读取整个类以读取变量数据 但这对我来说听起来很奇怪且错