set { return; 的目的是什么? }?

What is the purpose of set { return; }?

我在很多地方看到过下面的代码:

 namespace My.name.space
    {
        class myClass
        {       
            public CustomObject Name
            {
                get { return new CustomObject (this.Dog); }
                set { return; }
            }

        }
    }

set { return; } 的目的是什么?

我不明白集合 return 的用途。

我认为您可以完全删除 set 访问器。

None。有人不太清楚 read-only 属性 可以通过不包括 set

来更简单地表达
public Derp MuhDerp { get { return _derp; } }

CSharpie 在评论中提出的有趣观点...

如果你有一个set因为它是在接口中定义的,你可以添加set但省略return:

public Derp MuhDerp { get { return _derp; } set { } }

当然,如果接口定义了一个 setter,您可能应该确保它按预期工作:)

这就是 "don't do anything, I don't want to make an assignment"。就像 setter 中的 no-op。它也相当于一个空的 setter,即 set { }。真的,这是一个偏好问题;我猜有些人不喜欢空代码体。

当然,您通常不会那样做(正如 Will 指出的那样)。您只需使用 read-only 属性,但有一个关键区别:当使用 read-only 属性 时,尝试设置它会失败 at编译时间;如果您使用的是您询问的那个,那么它根本不会失败,它只会在运行时 "do nothing"。

您使用哪一个很大程度上取决于您希望您的应用程序做什么。我要指出的是,使用这种方法(而不是 read-only 属性)会导致代码脆弱,因为程序员可能没有意识到他们故意分配一个值的尝试被忽略了。

这与只读属性相同,但属性可以设置(显然没有意义)。

主要是给人一种有setter的错觉,嗯,有,但什么都不做。但这可能是为了让某些界面或父级保持快乐 class:

public CustomObject Name
{
   get { return new CustomObject( this.Dog ); }
   set { return; } // does absolutely nothing
}

这是一个class:

public abstract class A {
   public abstract void DoWork();
   public abstract string SomeProperty { get; set; }
}

这里给人一种实现抽象接口的错觉,但实际上并没有实现所有的东西:

public class B : A {
   public override string SomeProperty
   {
      get
      {
         return "whatever";
      }

      set
      {
         return; // keep interface happy
      }
   }

   public override void DoWork() {
      // I am not doing nothing but compiler is happy
   }
}

该代码也破坏了 Liskov Substitution Principle

C# 中的属性只是方法特例的语法糖。

一个"regular"属性喜欢

public int Foo {get;set;}

实际上(有点相似)

int _foo;
public int get_Foo() { return _foo;}
public void set_Foo(int value) { _foo = value;}

无论您如何指定自己,setter 和 getter

中会发生什么
public int Foo { get { return 47; } set { Console.WriteLine(value); } }

所以以你的例子为例,编译器会把它变成

public CustomObject get_Name() { return new CustomObject (this.Dog); }
public void set_Name(CustomObject value) { return; }

在 set-Method 中什么都不做。那么为什么会有人这样做呢? 有几个原因是有道理的:

  • 他们想稍后向该 setter 引入功能,因此它现在用作占位符
  • setter是必需的,因为属性来自一个接口,但是在那个具体实现中设置值是没有意义的
  • 一些 API 或基于反射的东西需要一个 set-method 即使它没有被使用。

这里有一些很好的答案(我知道这是一个老问题),但我想提供一些额外的上下文来说明它是什么、它何时有用以及我如何在生产中使用它代码。

第一,答案:这通常是没有用的。只需定义一个只读 属性。正如其他人所说,您完全正确,您可以删除该集合并获得 几乎 相同的效果 - 除了 属性 无法再分配给。

现在,这是有用的地方。对于我编写的许多较小的微服务,我使用 Azure Tables 进行存储。这是一个 key-value 数据库,其中您的键分为两部分:PartitionKey 和 RowKey。他们很漂亮self-explanatory。

通常我会得到几个小表(例如那些包含基本 application-managed 设置的表),它们没有意义使用 PartitionKey -- 即它们只有一个标识部分信息,例如 ID,以及值。

Azure.Data.Tables 库非常好,它提供了一个接口来实现您的 DTO。实现此接口通常如下所示:

using Azure;
using Azure.Data.Tables;

namespace SmartsheetIntegration.Qar.DataStores.Models;

public class MyDto : ITableEntity 
{
    public MyDto() {}

    public MyDto(string partitionKey, string rowKey)
    {
        PartitionKey = partitionKey;
        RowKey = rowKey;
    }

    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public DateTimeOffset? Timestamp { get; set; }
    public ETag ETag { get; set; }
}

现在,这些简单的应用程序设置怎么样?我想确保它们 never 以 PartitionKey 结束,因为我需要确定如果我想检索所有它们,我可以查询 'PartitionKey = ""'并取回一切。

对此的简单解决方案是:

using Azure;
using Azure.Data.Tables;

namespace SmartsheetIntegration.Qar.DataStores.Models;

public class MyDto : ITableEntity 
{
    public MyDto() {}

    public MyDto(string partitionKey, string rowKey)
    {
        PartitionKey = partitionKey;
        RowKey = rowKey;
    }

    public string PartitionKey
    {
        get => "";
        set { } // the same as set { return; }
    }
    public string RowKey { get; set; }
    public DateTimeOffset? Timestamp { get; set; }
    public ETag ETag { get; set; }
}

现在 Azure Tables 可以在它的库中为所欲为,但我可以保证保存到数据库中的 PartitionKey 永远是一个空字符串。

所以是的,这有用的情况并不多——但有一些接口实现是有意义的。