zoukankan      html  css  js  c++  java
  • 编写安全有效的 C# 代码

    Ref 局部变量和返回结果

    允许使用并返回对变量的引用的算法,这些变量在其他位置定义。 添加 ref 局部变量和 ref 返回结果可通过避免复制值或多次执行取消引用操作,允许更为高效的算法。

    public static ref int Find(int[,] matrix, Func<int, bool> predicate)
    {
        for (int i = 0; i < matrix.GetLength(0); i++)
            for (int j = 0; j < matrix.GetLength(1); j++)
                if (predicate(matrix[i, j]))
                    return ref matrix[i, j];
        throw new InvalidOperationException("Not found");
    }
    
    ref var item = ref MatrixSearch.Find(matrix, (val) => val == 42);
    Console.WriteLine(item);
    item = 24;
    Console.WriteLine(matrix[4, 2]);

    声明不可变值类型的只读结构

    使用 readonly 修饰符声明 struct 将通知编译器你的意图是创建不可变类型。

    readonly public struct ReadonlyPoint3D
    {
        public ReadonlyPoint3D(double x, double y, double z)
        {
            this.X = x;
            this.Y = y;
            this.Z = z;
        }
    
        public double X { get; }
        public double Y { get; }
        public double Z { get; }
    }

    结构可变时声明 readonly 成员

    向不改变状态的成员添加 readonly 修饰符有两个相关的好处。 首先,编译器会强制执行你的意图。 该成员无法改变结构的状态。 其次,访问 readonly 成员时,编译器不会创建 in 参数的防御性副本。

    public struct Point3D
    {
        public Point3D(double x, double y, double z)
        {
            _x = x;
            _y = y;
            _z = z;
        }
    
        private double _x;
        public double X
        {
            readonly get => _x;
            set => _x = value;
        }
    
        private double _y;
        public double Y
        {
            readonly get => _y;
            set => _y = value;
        }
    
        private double _z;
        public double Z
        {
            readonly get => _z;
            set => _z = value;
        }
    
        public readonly double Distance => Math.Sqrt(X * X + Y * Y + Z * Z);
    
        public readonly override string ToString() => $"{X}, {Y}, {Z}";
    }

     如果使用自动实现的属性,则编译器会将 readonly 修饰符添加到 get 访问器以获取读写属性。 对于仅具有 get 访问器的属性,编译器会将 readonly 修饰符添加到自动实现的属性声明中。

     请注意,readonly 修饰符对于只读属性是必需的。 编译器会假设 get 访问器可以修改状态;必须显式声明 readonly。 自动实现的属性是一个例外;编译器会将所有自动实现的 Getter 视为 readonly,因此,此处无需向 X 和 Y 属性添加 readonly 修饰符。

    尽可能对大型结构使用 ref readonly return 语句

    public struct Point3D
    {
        private static Point3D origin = new Point3D(0,0,0);
    
        public static ref readonly Point3D Origin => ref origin;
    
        // other members removed for space
    }

    将 in 修饰符应用于大于 System.IntPtr.Size 的 readonly struct 参数

    in 关键字补充了现有的 ref 和 out 关键字,以按引用传递参数。 in 关键字指定按引用传递参数,但调用的方法不修改值。

    这种做法通常可以提高大于 IntPtr.Size 的只读值类型的性能。 对于简单类型(sbytebyteshortushortintuintlongulongcharfloatdoubledecimal 和 bool 以及 enum 类型),任何潜在的性能提升都是极小的。 实际上,对于小于 IntPtr.Size 的类型,使用按引用传递可能会降低性能。

    避免在 in 参数中使用可变结构

    private static double CalculateDistance(in Point3D point1, in Point3D point2)
    {
        double xDifference = point1.X - point2.X;
        double yDifference = point1.Y - point2.Y;
        double zDifference = point1.Z - point2.Z;
    
        return Math.Sqrt(xDifference * xDifference + yDifference * yDifference + zDifference * zDifference);
    }

     如果没有语言保证,编译器必须在调用任何未标记为 readonly 修饰符的成员之前创建参数的临时副本。这些副本会降低性能,使得按值传递比按只读引用传递速度更快。

    相反,如果距离计算使用不可变结构 ReadonlyPoint3D,则不需要临时对象:

    private static double CalculateDistance3(in ReadonlyPoint3D point1, in ReadonlyPoint3D point2 = default)
    {
        double xDifference = point1.X - point2.X;
        double yDifference = point1.Y - point2.Y;
        double zDifference = point1.Z - point2.Z;
    
        return Math.Sqrt(xDifference * xDifference + yDifference * yDifference + zDifference * zDifference);
    }
  • 相关阅读:
    学习进度总结表
    关于软件工程的问题
    自我介绍
    web安全
    spring profile
    spring 装配
    python Descriptor (描述符)
    python string intern
    Java 对象内存占用
    java jdb命令详解
  • 原文地址:https://www.cnblogs.com/yetsen/p/13454009.html
Copyright © 2011-2022 走看看