有没有办法在C#中使用代码重用来实现多个属性?

dlc*_*ers 5 c# properties

我有一个类是这样的类:

public class Abc
{
   public string City
   {
      get { return _getValue(); }
      set { _setValue(value); }
   }
   public string State
   {
      get { return _getValue(); }
      set { _setValue(value); }
   }
   private string _getValue()
   {
      // determine return value via StackTrace and reflection
   }
   ...
}
Run Code Online (Sandbox Code Playgroud)

(是的,我知道StackTrace /反射很慢;不要惹我生气)

鉴于所有属性都被声明为相同,我能够做的就是有一些简单/干净的方式来声明它们,而不需要反复复制相同的get/set代码.
我需要所有属性的Intellisense,这排除了使用例如.ExpandoObject.

如果我在C/C++的土地上,我可以使用一个宏,例如:

#define DEFPROP(name) \
   public string name \
   { \
      get { return _getValue(); } \
      set { _setValue(value); } \
   } \
Run Code Online (Sandbox Code Playgroud)

然后:

public class Abc
{
   DEFPROP(City)
   DEFPROP(State)
   ...
}
Run Code Online (Sandbox Code Playgroud)

但当然这是C#.

那么......任何聪明的想法?

####编辑###
我想我原来的帖子不够清楚.
我的帮助函数_getValue()根据调用的Property执行一些自定义查找和处理.它不仅存储/检索简单的特定于prop的值.
如果我需要的只是简单的值,那么我只使用自动属性

public string { get; set; }
Run Code Online (Sandbox Code Playgroud)

并完成它,并不会问这个问题.

And*_*air 5

首先:CallerMemberNameAttribute注入调用成员名称,因此不需要反射:

public class Abc
{
   public string City
   {
      get { return _getValue(); }
      set { _setValue(value); }
   }
   public string State
   {
      get { return _getValue(); }
      set { _setValue(value); }
   }
   private string _getValue([CallerMemberName] string memberName = "")
   {
   }

   private void _setValue(string value,
                          [CallerMemberName] string memberName = "")
   {
   }
}
Run Code Online (Sandbox Code Playgroud)

其次:通过利用.4文件生成的T4模板,可以实现类型成员的生成:

<#@ output extension=".cs" #>
<#
var properties = new[]
{
    "City",
    "State"
};
#>
using System.Runtime.CompilerServices;

namespace MyNamespace
{
    public class Abc
    {
<# foreach (var property in properties) { #>
        public string <#= property #>
        {
            get { return _getValue(); }
            set { _setValue(value); }
        }
<# } #>
        private string _getValue([CallerMemberName] string memberName = "") {}
        private void _setValue(string value, [CallerMemberName] string memberName = "") {}
    }
}
Run Code Online (Sandbox Code Playgroud)

您甚至可以卸载_setValue_getValue包含文件,以便为其他模板提供可重用性.

T4模板确实具有优于宏的优势,可以随时重新生成代码.因此,即使在初始生成之后,也可以应用对源代码的调整(可能是实现自适应或属性重命名).


Zot*_*tta 0

有人弄清楚了如何在 c# 中使用 c 预处理器

请参阅/sf/answers/1099263021/

但是:您应该避免使用堆栈跟踪来达到您的目的!!!!将字符串传递给 _getValue("name") 或自动生成字段。如果您使用堆栈跟踪,则必须停用方法内联(简单)以及尾部调用优化(不确定这是否可能)。