使用“模板”在类中实现类似的属性.在c#

本文关键字:属性 实现 使用 模板 | 更新日期: 2023-09-27 18:02:49

我一直想知道在c#中是否有一种方法来定义一个"模板"类中的多个属性。我的意思是:

让我们假设我有以下类

class MyCLass
{
    public int  IntVal1 { get {...}; set{...} }
    public byte IntVal2 { get {...}; set{...} }
    ....
    public long IntValN { get {...}; set{...} }
}

我没有在get和set访问器中编写任何具体的实现,但思想是所有这些属性都有非常相似的实现——区别可能是它们操作于具有不同类型的类的不同成员,但作为一个整体,它们看起来都是相似的。

我的想法是找到一种方法来定义某种(姑且称之为)"模板"。使用一些参数可能可以用来声明所有这些属性,而不需要编写每个属性的实际实现-可能使用属性!?!

我想我需要的是类似于C宏。

使用“模板”在类中实现类似的属性.在c#

简短的回答是"不",但是你可以做一些事情来减少重复。例如,考虑:

private bool SetField<T>(ref T field, T value,
    [CallerMemberName] string memberName = null)
{
    if (!EqualityComparer<T>.Default.Equals(field, value))
    {
        field = value;
        var handler = PropertyChanged;
        if (handler != null) handler(this,
            new PropertyChangedEventArgs(memberName));
        return true;
    }
    return false;
}

可以用来减少开销,例如:

private string bar;
public string Bar
{
    get { return bar; }
    set { SetField(ref bar, value); }
}

是的,如果我理解正确的话,在c#中我们使用泛型:

class MyCLass<T>
{
    public T Val { get {...}; set{...} }
}

T定义了你想要"模板"的类型。

然后像这样使用这个类:

var myClassInt = new MyClass<int>();
myClassInt.Val // is an integer

您可以查看T4 templates并从中生成代码:http://msdn.microsoft.com/en-us/library/vstudio/bb126445.aspx

如果您使用分部类,您可以使用一个用于生成的代码,另一个用于非生成的代码。

这里有一个很好的教程:http://t4-editor.tangible-engineering.com/How-Do-I-With-T4-Editor-Text-Templates.html

在基类中需要一个虚拟的受保护方法。这个方法将设置属性。在子类中,你可以继承一个基实现或重写Init/Set/Get方法,并创建一个自定义实现。

abstract class BaseMyClass
{
    public BaseMyClass(arg1, arg2,...)
    {
        Init(arg1, arg2,...);
    }
    public int  IntVal1 { get {...}; set{...} }
    public byte IntVal2 { get {...}; set{...} }
    public byte IntVal3 
    { 
        get 
        {
            return GetIntVal3(); 
        } 
        set
        {
            SetIntVal3(value);
        }
    }
    protected void virtual Init(arg1, arg2,...)
    {
         //Init properties
    }
    protected virtual byte GetIntVal3()
    {
         //Implementation
    }
    protected virtual void SetIntVal3(value)
    {
         //Implementation
    }
}
class MyCLass : BaseMyClass
{
    public MyCLass(arg1, arg2, ...): base(arg1, arg2,...)
}
class AnotherMyCLass : BaseMyClass
{
    public MyCLass(arg1, arg2, ...): base(arg1, arg2,...)
    protected override void Init(arg1, arg2,...)
    {
         //Init properties
    }
}