首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HAA0502显式新引用类型分配

HAA0502显式新引用类型分配
EN

Stack Overflow用户
提问于 2019-09-27 16:47:27
回答 1查看 1.1K关注 0票数 5

我有ASP.Net Core 2.1C#应用程序。我正在使用Clr堆分配分析器

https://marketplace.visualstudio.com/items?itemName=MukulSabharwal.ClrHeapAllocationAnalyzer

其中一个方法如下所示

Ex#1

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services) {

services.AddSingleton<IPocoDynamo>(serviceProvider => {
    var pocoDynamo = new PocoDynamo(serviceProvider.GetRequieredService<IAmazonDynamoDB>());
    pocoDynamo.SomeMethod();
    return pocoDynamo;
});

}

Ex.#2

代码语言:javascript
复制
public async Task<EventTO> AddEvent(EventTO eventObj)
{
  try
    {       
      throw new Exception("Error!");
    }
 catch (Exception ex)
 {
   Logger.Log(ex, eventObj);
   return null;
  }
}

我在整个应用程序中使用DI。但是,在分析器发现new关键字的地方,它的警告是

HAA0502显式新引用类型分配

此外,无论在哪里使用Lambda表达式,它都是警告(如在ex#1中)。

代码语言:javascript
复制
Warning HAA0301 Heap allocation of closure Captures:

是什么导致了这一问题&如何解决这一问题?

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2021-05-13 17:46:03

堆分配分析器用于标记代码执行的所有分配。这不是您想要一直做的事情:请考虑以下愚蠢的代码

代码语言:javascript
复制
        public static string MyToString(object? o)
        {
            if (o == null)
                throw new ArgumentNullException(nameof(o)); // HAA0502 here

            return o.ToString() ?? string.Empty;
        }

分析器将以警告的形式发出HAA0502,作为标记行上的信息,以告诉您正在分配一个新实例。现在,在这种情况下,您所做的事情是显而易见的,这是一个微不足道的警告,但是分析器的目的是帮助您发现可能会将代码转换为更慢的代码的讨厌的分配。

现在考虑下面这个愚蠢的代码:

代码语言:javascript
复制
        public static void Test1()
        {
            for (int i = 0; i < 100; i++)
            {
                var a = i + 1;

                var action = new Action(
                    () =>   // HAA0301 Heap allocation of closure Capture: a
                    {
                        Console.WriteLine(a);
                    }
                );

                action();
            }
        }

除了HAA0502将在new Action(上标记,因为我们正在创建一个新的对象,在lambda上还有一个额外的警告:HAA0301。这就是分析器变得更有用的原因:在这里,分析器告诉您,运行时将创建一个包含捕获的变量a的新对象。如果您对此不熟悉,您可能会在代码中考虑将其转换为类似的内容(仅用于解释目的):

代码语言:javascript
复制
        private sealed class Temp1
        {
            public int Value1 { get; }

            public Temp1(int value1)
            {
                Value1 = value1;
            }

            public void Method1()
            {
                Console.WriteLine(Value1);
            }
        }

        public static void Test1()
        {
            for (int i = 0; i < 100; i++)
            {
                var a = i + 1;

                var t = new Temp1(a);
                t.Method1();
            }
        }

在后一段代码中,很明显,在每次迭代时,您都分配一个对象。

您可能面临的主要问题是:正在分配对象为问题?在99.9%的情况下它不是一个问题,而且您可以接受编写可读的、精确的和简洁的代码的简单性,而无需处理低级别的细节;但是,如果您遇到性能问题(即其余的0.01%),分析器可能会变得非常方便,因为它在一张照片中显示了您的或代表您的编译器正在分配一些东西。分配对象需要一个未来的垃圾回收器循环来回收内存。

对于您的代码,您正在使用工厂模式通过DI初始化服务:该代码只运行一次。因此,您分配一个新对象并不奇怪。这样您就可以安全地抑制这部分代码上的警告。您可以使用IDE来生成抑制代码。这就是为什么我建议将分析器禁用,并且只在搜索性能问题时启用它。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58138603

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档