c#结构与类性能,设计重点

c#结构与类性能,设计重点,c#,class,struct,C#,Class,Struct,使用struct可以获得多大的性能提升?我是否应该设计专注于最大限度地使用struct而不是类的应用程序 我是否可以将我的类转换为struct,并尽可能将函数移动到另一个静态类中?的优点是: ✓ 如果是实例,请考虑定义结构而不是类。 类型很小,通常寿命很短,或者通常嵌入到 其他物体 避免定义结构,除非该类型具有所有 以下特点: 它在逻辑上表示单个值,类似于基元类型 (整数、双精度等) 它的实例大小小于16字节 它是不变的 它不必经常装箱 此外,MSDN还提供了 我是否应该设计专注于最大限度地使用

使用struct可以获得多大的性能提升?我是否应该设计专注于最大限度地使用struct而不是类的应用程序

我是否可以将我的类转换为struct,并尽可能将函数移动到另一个静态类中?

的优点是:

✓ 如果是实例,请考虑定义结构而不是类。 类型很小,通常寿命很短,或者通常嵌入到 其他物体

避免定义结构,除非该类型具有所有 以下特点:

  • 它在逻辑上表示单个值,类似于基元类型 (整数、双精度等)
  • 它的实例大小小于16字节
  • 它是不变的
  • 它不必经常装箱
  • 此外,MSDN还提供了

    我是否应该设计专注于最大限度地使用struct而不是类的应用程序

    这取决于您试图实现什么。当您有一个小的结构,您试图实现它,它的行为类似于值时,就会使用结构。所以说在类上使用struct不是一种理想的说法或方法。

    简单的回答是“你可以,但你不应该”

    类和结构之间的主要区别在于,结构定义值类型,而类定义引用类型。因此,您实际上不能仅仅用“struct”替换“class”单词并移动函数,因为上述差异可能会严重影响程序的行为。然后,如果你从头开始设计一个新的应用程序,你可以考虑是否使用适当的结构或类来定义逻辑对象,但是代码必须记住这一点。
    我希望这有帮助

    将结构转换为类不会自动提高应用程序的性能。
    这取决于如何使用它们,而不是如何使用类对象

    如果创建并销毁一个类的许多对象,则可以重用该类的对象,也可以创建一个结构并重用它
    (你看,你也可以通过一个类来实现这一点)

    调用方法并发送参数或返回值时,
    类通过引用传递,结构通过值传递
    因此,如果您花很多时间,您可能会享受性能提升。
    (同样,通过良好的编程,您甚至可以通过将数据作为包含方法的类的字段来避免将其一直传递给方法)

    关于第二个问题,
    在结构中也可以有方法,不必将它们移动到静态类中

    struct SimpleStruct
    {
        private int xval;
    
        public int X
        {
            get 
            {
                return xval;
            }
            set 
            {
                if (value < 100)    xval = value;
            }
        }
    
        public void DisplayX()
        {
            Console.WriteLine("The stored value is: "+xval);
        }
    }
    
    struct SimpleStruct
    {
    私人int xval;
    公共整数X
    {
    得到
    {
    返回xval;
    }
    设置
    {
    如果(值<100)xval=值;
    }
    }
    public void DisplayX()
    {
    Console.WriteLine(“存储值为:“+xval”);
    }
    }
    

    msdn建议(在另一个答案中列出)提供了一些指导。对于性能,应该考虑它们的用法以及结构和类之间的区别。最重要的是,仅当类型是实际值类型(即具有值语义)时才使用结构。将类用于值类型,或将结构用于本应为引用类型的对象,将很快产生与意外复制或意外引用混淆的结果。还要记住,结构应该始终是不可变的

    只有在对性能非常敏感的情况下,才应该忽略这些基本规则中的任何一条(例如:框架破坏了List.Enumerator结构的规则!)

    结构与类的性能注意事项:

    如果将结构作为参数传递给方法,则每次都将创建结构的副本。这就是为什么文档建议不要使结构大于16字节的原因

    double Distance(Vector3D a, Vector3D b)   // Copies both 24-byte structs
    {
       return Math.Sqrt((a.X - b.X *....);
    }
    
    在上面的场景中,3个双精度的3D向量将产生24个字节,并且比推荐的16个大,但我仍然认为结构是有意义的,因为它显然是一种值类型,特别是你有一个包含两个双精度(16个字节)的Vector2D,这是一个结构

    有效地使用结构的关键,以及它们的性能真正出色的地方,是将它们用于缓存局部性并避免许多分配。要重复使用上面的向量示例,请使用此方法

    double AverageDistanceFromOrigin(Vector3D[] points) // Single reference passed
    {
       double sum = 0.0;
       for(...)                                         
          sum += Math.Sqrt(points[i].X... + ... + ...)  // No copies
       return sum/points.Length;
    }
    
    您可能会看到有利于结构的良好性能差异。原因是现在您正在向该方法传递一个引用(数组),因此每次调用复制结构时没有额外的开销(请注意,该方法不会为数组中的每个条目调用distance方法)

    结构数组也在内存中连续排列,如[x1,y1,z1,x2,y2,…],因此cpu将一次加载16个坐标到缓存中,导致很少的缓存未命中。将其与
    类Vector3D
    实现进行比较:现在将分配一个向量数组,数组中的每个条目也将是一个引用,必须进行堆分配,然后进行垃圾收集。该数组现在是一个引用数组[ref-to-v1,ref-to-v2,ref-to-v3],每个引用都可能在堆中有任何地址,并且不可能彼此相邻。这可能会导致比struct情况更多的缓存未命中

    • 仅当类型具有值语义时才使用结构(反之亦然)
    • 不要将大型结构单独传递给方法;对结构的列表/数组进行操作以避免复制
    • 不要将16字节限制视为硬限制:可以使用更大的结构,但请记住避免将它们单独传递给方法。<李>
    使用struct可以获得多大的性能提升

    因为“可能”的答案是你可以快很多倍

    H