Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用get vs属性vs方法_C# - Fatal编程技术网

C# 使用get vs属性vs方法

C# 使用get vs属性vs方法,c#,C#,如果我在一个类中有一个私有属性,我想知道以下三种场景(内存使用、可用性、最佳实践等)在技术上有什么区别: 除了能够在myString1中设置值而不是在myString2或myString3中设置值外,我还想知道这些值在效率方面有什么不同?我个人更喜欢那些没有副作用的属性,如果某些东西是在运行中计算的,那么就显式地使用getter。例如: class User { private string username; public string Username {

如果我在一个类中有一个私有属性,我想知道以下三种场景(内存使用、可用性、最佳实践等)在技术上有什么区别:


除了能够在myString1中设置值而不是在myString2或myString3中设置值外,我还想知道这些值在效率方面有什么不同?

我个人更喜欢那些没有副作用的属性,如果某些东西是在运行中计算的,那么就显式地使用getter。例如:

class User {
    private string username;

    public string Username {
        get { return username; }
        set { username = value; }
    }

    public Post GetLatestPost() {
        // query the database or whatever you do here.
    }
}
我看到的很多API似乎都是这样做的。希望有帮助。

这是个好问题:

你有这样的选择:

private string myString = "hi!";   //Private Field

public string MyString             //Property created to the private field
{
  get {return myString;}
}

public string myString {get; private set;}   //VS2008 automatic properties

public string getMyString()                  //Method Way
{
   return myString;
}
正如您所看到的,这个想法是相同的,不违反封装原则。使用一个您觉得更舒服的,所有这些都达到了目标,但我推荐property way或VIsual Studio 2008 automatic属性

比方法更简洁明了

希望这有帮助


问候

就最佳实践而言

class testClass
{
   private string _myString;

   public string myString { get { return _myString; } set { _myString = value; } }

   public testClass()
   {
      myString = "Hello";  // Initial value.
   }
}
通常建议使用,因为它实现了封装(隐藏内部状态,以便所有操作都通过方法/接口)。当然,setter和getter通常是方法本身

在C#3.0中,您可以将上述内容替换为:

class testClass 
{    
  public string myString { get; set; }

  public testClass()
  {
      ...
  }
}

就效率而言,您确实不应该考虑直接访问变量是否比访问属性更有效。差异如此之小(如果有的话),而最佳实践指南如此明确,以至于您在担心效率时误入歧途。

所有这些方法在编译目的上都有很大不同,尽管在使用方面非常相似。我将尝试简要总结这些差异:

  • 这是一个简单的私有实例变量。它很容易成为引用时最有效的方法

  • 这是一个只读属性(即get而非set访问器)

  • 这是一个正常的无参数函数。我怀疑您提供这些示例纯粹是为了进行比较,并意识到这样一个函数是完全无用的(在几乎所有情况下,私有属性也是如此)。布局(即一行中的所有内容)也相当糟糕

  • 方法2和3与方法1相比效率同样低下,因为它们都涉及函数调用的开销。我不知道它们都编译成什么样的CIL代码(也许其他人可以生成),但它们肯定还包含一些指令,而引用
    myString1
    应该只需要CIL中的一条指令

    在不了解更多上下文的情况下,我不确定是否可以对最佳实践做出非常有用的评论,但方法2(即私有财产)通常被视为毫无用处。在我看来,第三种方法永远不应该使用(它乞求变成一种财产)。我认为您真正想要的只是一个普通的旧私有变量,所以一定要使用第一个声明。公共值应始终作为属性而不是类中的变量(即属性的私有/受保护支持变量)进行访问,但这与您的问题稍微无关。(无论如何,您可以在快速搜索中找到大量讨论这一问题的资源。)最后,请注意,如果您的“属性”将是只读的(即,在任何时候都不修改),那么您确实希望使用常量,即
    private const string myString1=“hello”


    希望这有助于澄清一些问题。

    以上所有关于设计、风格等的讨论都是有效的。但问题在于性能。很容易测试。围绕每个调用包装一些计时器,重复到int32.Max。 在我的机器上,下面的代码显示myString1要快得多。(请注意,我必须更改类定义以公开成员):

    private void按钮2\u单击(对象发送者,事件参数e)
    {
    //性能测试
    testClass t=新的testClass();
    System.Diagnostics.Stopwatch sw1=新的System.Diagnostics.Stopwatch();
    sw1.Start();
    对于(int i=0;i
    我尽可能遵循以下规则:

    • 字段应保密
    • 属性应用于公开数据
    • 应该使用方法来执行操作
    显然,在某些情况下,性能的每一次下降都很重要,但总的来说,我会尝试遵循最佳实践,直到分析告诉您需要优化为止


    这里有一篇很好的文章:

    这已经被回答了无数次。我相信答案是肯定的,但请相信我,我说我在发布之前在这个网站上搜索了大约10分钟。因为“易于测试”,我认为你搞砸了。第一个循环可能完全由编译器优化,因为它什么也不做,但是第二个和第三个循环是函数调用,不能很容易地优化。Tr
    class testClass 
    {    
      public string myString { get; set; }
    
      public testClass()
      {
          ...
      }
    }
    
        private void button2_Click(object sender, EventArgs e)
        {
            //performance test
            testClass t = new testClass();
            System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch();
            sw1.Start();
            for (int i = 0; i < int.MaxValue; i++)
            {
                string result = t.myString1;
            }
            sw1.Stop();
    
            System.Diagnostics.Stopwatch sw2 = new System.Diagnostics.Stopwatch();
            sw2.Start();
            for (int i = 0; i < int.MaxValue; i++)
            {
                string result = t.myString2;
            }
            sw2.Stop();
    
            System.Diagnostics.Stopwatch sw3 = new System.Diagnostics.Stopwatch();
            sw3.Start();
            for (int i = 0; i < int.MaxValue; i++)
            {
                string result = t.myString3();
            }
            sw3.Stop();
            MessageBox.Show(string.Format("Direct: {0}, Getter: {1}, Method: {2}"
                , sw1.ElapsedMilliseconds.ToString()
                , sw2.ElapsedMilliseconds.ToString()
                , sw3.ElapsedMilliseconds.ToString()));
        }
    
    
    class testClass 
    { 
        public string myString1 = "hello";
        public string myString2 { get { return "hello"; } }
        public string myString3() { return "hello"; } 
    }