代码改变世界

[FxCop.性能规则]1. 避免调用需要Unboxing

  Colin Han  阅读(1942)  评论(1编辑  收藏  举报

1.     避免调用需要Unboxing

翻译概述:

JavaC#中,所有的数据类型都是从System.Object继承来的,包括数值型类型。这样的设计使我们可以用相同的方式处理引用类型和值类型。从而为我们提供了很大的灵活性,实现更加通用的算法。

但是,将所有数据都放在堆中进行管理无疑会降低程序的性能。因此,C#(包括Java)中都将数据类型分为值类型和引用类型,在常规状态下,值类型局部变量会放在栈中进行管理,从而实现更加高的效率。

这时候就存在将值类型转换为引用类型的问题,因为可能我们的方法只接受引用类型的参数。因此在C#Java中都有BoxingUnboxing的概念。当我们将一个值类型数据复制给一个引用性变量时,会将值类型数据作Boxing处理。在做反向操作时,进行Unboxing处理。相当于作了一个盒子来装这个这类型数据。

但是,正如下文中所说,做Unboxing操作会消耗更多的系统资源,因此,微软建议尽量避免进行Unboxing操作。

 另外,据说C#的范型使用了一定的技术实现了值类型和引用类型同等处理的能力,没有使用BoxingUnboxing,因此效率和直接使用强类型方法相当。因此下文中的例子中演示了使用范型替代ArrayList来提高效率。

引起的原因:

调用一个返回object类型值得函数,并且将返回值转换为一个值类型。

描述:

将一个object实例转换为之类型会调用Unboxing操作。当调用Unboxing操作时,运行时系统会首先判断这个object实例是否是空引用,然后判断其中存储的数据是不是一个请求类型的数据。如果这两条都满足了,运行时系统会返回一个引用到其中存储的数据,并且将数据从堆中复制到栈中。这些操作会影响执行效率。

修复:

实现一个强类型的方法,并调用这个新方法。如果需要,可以使用范型来实现。

例外:

如果不能实现一个对应的强类型方法,可以忽略这条规则。如果性能并不是关心的重点,可以完全忽略这条规则。

例程:

下面的例子中包含一个方法"WeaklyTyped",这个方法违反了这条规则。例子中还包括另外一个方法”StronglyTyped”,它修正了这个问题。

 
代码见原文

 

下面的例子中包含一个方法”WeaklyTyped”,这个方法违反了这条规则,例子中还包括另外一个方法"UsesGenerics",它使用范型修正了这个问题。

 

代码见原文

 

原文引用:

Avoid calls that require unboxing

TypeName:

AvoidCallsThatRequireUnboxing

CheckId:

CA1808

Category:

Microsoft.Performance

Message Level:

Warning

Certainty:

90%

Breaking Change:

NonBreaking


Cause: A call is made to a method that returns a System.Object instance and the instance is cast to a value type.

Rule Description

Casting an Object instance to a value type invokes an unboxing operation. In an unboxing operation, the runtime first checks whether the instance is null and then determines whether the instance represents the specified value type. If so, the runtime returns a reference to the data portion of the instance and copies the fields from the heap to the stack. These operations degrade performance.

How to Fix Violations

To fix a violation of this rule, replace the call with an equivalent strongly typed method. Use generics if available.

When to Exclude Messages

Exclude a message from this rule if an equivalent strongly typed method is not available. It is also safe to exclude a message from this rule, or ignore the rule entirely, if performance is not a concern.

Example Code

The following example shows a method, WeaklyTyped, which violates the rule and a method, StronglyTyped, which satisfies the rule.

[C#]

using System;
 
namespace PerformanceLibrary
{
   
public interface IWork
   
{
      
object DoWork();
   }

 
   
public class Work : IWork
   
{
      
object IWork.DoWork()
      
{
         
return 3;
      }

 
      
public int DoWork()
      
{
         
return 3;
      }

   }

 
   
public class NeedsWork
   
{
      
public void WeaklyTyped()
      
{
         IWork iwork 
= new Work();
 
         
// The following call violates the rule.
         int x = (int)iwork.DoWork();
      }

 
      
public void StronglyTyped()
      
{
         Work work 
= new Work();
         
int x = work.DoWork();
      }

   }

}


The following example shows a method, WeaklyTyped, which violates the rule and a method, UsesGenerics, which satisfies the rule using generics.

[C#]

using System;
using System.Collections;
using System.Collections.Generic;
 
namespace PerformanceLibrary
{
   
public class AvoidBoxing
   
{
      
public void WeaklyTyped()
      
{
         ArrayList weaklyTypedList 
= new ArrayList();
         weaklyTypedList.Add(
3);
         weaklyTypedList.Add(
5);
         weaklyTypedList.Add(
11);
 
         
int sum = 0;
         
for(int i = 0; i < weaklyTypedList.Count; i++)
         
{
            
// The following call violates the rule.
            sum += (int)weaklyTypedList[i];
         }

      }

 
      
public void UsesGenerics()
      
{
         List
<int> stronglyTypedList = new List<int>();
         stronglyTypedList.Add(
3);
         stronglyTypedList.Add(
5);
         stronglyTypedList.Add(
11);
 
         
int sum = 0;
         
for(int i = 0; i < stronglyTypedList.Count; i++)
         
{
            sum 
+= stronglyTypedList[i];
         }

      }

   }

}


[Visual Basic]

Imports System
Imports System.Collections
Imports System.Collections.Generic
 
Namespace PerformanceLibrary
 
   
Public Class AvoidBoxing
   
      
Sub WeaklyTyped()
      
         
Dim weaklyTypedList As New ArrayList()
         weaklyTypedList.Add(
3)
         weaklyTypedList.Add(
5)
         weaklyTypedList.Add(
11)
 
         
Dim sum As Integer = 0
         
For I As Integer = 0 To weaklyTypedList.Count - 1
 
            
' The following call violates the rule.
            sum = sum + DirectCast(weaklyTypedList(I), Integer)
         
Next
 
      
End Sub

 
      
Sub UsesGenerics()
      
         
Dim stronglyTypedList As New List(Of Integer)
         stronglyTypedList.Add(
3)
         stronglyTypedList.Add(
5)
         stronglyTypedList.Add(
11)
 
         
Dim sum As Integer = 0
         
For I As Integer = 0 To stronglyTypedList.Count - 1
            sum 
= sum + DirectCast(stronglyTypedList(I), Integer)
         
Next
 
      
End Sub

 
   
End Class

 
End Namespace

 

编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示