C# - 访问对象变量

时间:2015-02-27 11:00:56

标签: c# .net oop

我想知道消耗对象值的性能方面的最佳方法。我已经看到了缓存值并在后面部分使用的代码。它在使用方面看起来很干净。性能明智哪个更好,为什么。这可能是一个简单的问题,但我相信很多人都想知道答案。

以下是示例代码。

//Class with variables
Cls A
{   
   String a = "aaa";
   String b = "bbb"; 
   String c = "ccc";  
}

//Cls B with Cls A object and initialized
Cls B
{  
  A a1 = new A(); 
}

**One**
B b1 = new B();
Str t1 = b1.a1.a;
Str t2 = b1.a1.b;

**Two**
B b1 = new B();
A c1 = b1.a1;
Str t1 = c1.a;
Str t2 = c1.b;

堆叠或堆叠是否会发挥作用

2 个答案:

答案 0 :(得分:1)

特定情况下,它们可能是等效的,因为a1是一个字段。

一般来说,如果a1是一个属性,你就不知道它是如何“支持”的(它保存了值)。

如果它将其值保存在字段上,那么访问该属性几乎/快于缓存其值。如果必须每次/必须访问Dictionary /其他复杂对象时计算其值,那么可以更好地缓存它。

在ASP.NET中,a1通常可以是Session[...] / ViewState[...]个对象(最后它们就像Dictionary一样,所以它们以类似的方式工作 - 明智的),所以如果你在紧张的forwhile周期中访问它,有时最好“缓存”它的值。

一般来说,这是过早的优化。除非你需要,否则你不会这样做。

举一些经典的例子:

public class MyClass {
    // A field
    public int Fast1;

    // An automatic property backed by a field
    public int Fast2 { get; set; }

    // A property backed by a field
    public int Fast3 {
        get { return Fast1; }
    }

    // Each time you call this property, some calculation is done
    public int LittleSlow1 {
        get {
            int j = 0;
            for (int i = 0; i < 1000000; i++) {
                if (i > j) {
                    i = j;
                }
            }
            return j;
        }
    }

    // This property is backed by a collection. There is a
    // scan of the collection to retrieve the value.
    public int LittleSlow2 {
        get {
            return ignoreme["LittleSlow1"];
        }
    }

    public Dictionary<string, int> ignoreme = new Dictionary<string, int>();
}

反对属性的一个原因是它们与myprop = 5x = myprop + 1中使用它们的方式几乎完全相同,但是就这种方式而言,它们“隐藏”给程序员潜在的成本使用它们,而当程序员调用方法时,他知道该方法可能很昂贵。

答案 1 :(得分:0)

为此,一个好的旧基准可以定量地给你你想要的东西。

测试方法

class A {
    public string a = "aaa", b = "bbb", c = "ccc";
}

class B {
    public A a1 = new A();
}

class Program {
    static void Main(string[] args) {

        int counter = 0;
        int counter2 = 0;

        Stopwatch sw = new Stopwatch();

        // Method 1
        sw.Start();

        B b1 = new B();
        while (sw.ElapsedMilliseconds < 5000) {
            string t1 = b1.a1.a;
            string t2 = b1.a1.b;
            counter++;
        }

        sw.Stop();
        sw.Reset();

        // Method 2
        sw.Start();

        B b2 = new B();
        A c1 = b2.a1;
        while (sw.ElapsedMilliseconds <5000) {
            string t3 = c1.a;
            string t4 = c1.b;
            counter2++;
        }

        sw.Stop();

        Console.WriteLine("Counter={0}", counter);
        Console.WriteLine("Counter2={0}", counter2);
        Console.ReadKey();
    }
}

我测试两种方法5秒钟为属性赋值。

注意:这可以设计得更好,但这仍然会给我们提供合理准确的结果。

在此之后运行5次,结果如下:

输出(注意:我们测量哪种方法的执行次数越多越好越好)

Counter=33054729
Counter2=33783643

Counter=32599924
Counter2=33610612

Counter=52581701
Counter2=53822872

Counter=50725227
Counter2=51932970

Counter=32688454
Counter2=32577850

正如您所看到的,结果相对接近,但第二种方法整体似乎更快。可能的解释可能是在property内调用方法的开销成本。如果其他人可以提供更好的解释,请告诉我。