我怎样才能避免使用类似枚举的属性进行所有这些重复?

How could I avoid all this repetition with enumerated-like properties?

我刚刚在 class 中发现了一个由索引不匹配引起的隐蔽错误,这是由于代码重复且类似序列。

我的问题:是否有另一种更明智的方法来公开属性(与 WPF 一起用于数据绑定)而无需所有这些可怕的重复?

代码(包括对最差部分的评论):

public class MemoryTable
{

    public string Name { get; private set; }

    int TableNumber { get; set; }
    DeviceWrapper _device;

    public MemoryTable(DeviceWrapper deviceWrapper, string name, int number)
    {
        _device = deviceWrapper;
        Name = name;
        TableNumber = number;
    }

    public float P1 
    {
        get { return getVal(0); } 
        set { setVal(0, value); }
    }

    public float P2
    { 
        get { return getVal(1); }
        set { setVal(1, value); }
    }

    public float P3  // Notice that I have three numerical values 
    {
        get { return getVal(2); }
        set { setVal(2, value); }   // I typed "1" here accidentally... Bug!
    }

    public float P4
    {
        get { return getVal(3); }
        set { setVal(3, value); }
    }

    public float P5
    {
        get { return getVal(4); }
        set { setVal(4, value); }
    }

    public float P6
    { 
        get { return getVal(5); }
        set { setVal(5, value); }
    }

    public float P7
    { 
        get { return getVal(6); }
        set { setVal(6, value); }
    }

    public float P8
    { 
        get { return getVal(7); }
        set { setVal(7, value); }
    }



    private float getVal(int pos)
    {
        return _device.GetCalibrationValue(TableNumber, pos);
    }

    private void setVal(int pos, float val)
    {
        _device.SetCalibrationValue(TableNumber, pos, val);
    }



    internal void FillWithValue(float value)
    {
        P1 = value;
        P2 = value;
        P3 = value;
        P4 = value;
        P5 = value;
        P6 = value;
        P7 = value; 
        P8 = value;  // "foreach" by hand, really? :o(
    }
}

编辑:XAML,接受答案的建议:

        <DataGrid.Columns>
            <DataGridTextColumn Header="A1" Binding="{Binding [0]}" Width="100"/>
            <DataGridTextColumn Header="B1" Binding="{Binding [1]}" Width="100"/>
            <DataGridTextColumn Header="A2" Binding="{Binding [2]}" Width="100"/>
            <DataGridTextColumn Header="B2" Binding="{Binding [3]}" Width="100"/>
            <DataGridTextColumn Header="A3" Binding="{Binding [4]}" Width="100"/>
            <DataGridTextColumn Header="B3" Binding="{Binding [5]}" Width="100"/>
            <DataGridTextColumn Header="A4" Binding="{Binding [6]}" Width="100"/>
            <DataGridTextColumn Header="B4" Binding="{Binding [7]}" Width="100"/>
        </DataGrid.Columns>

您可以绑定到索引属性:

public float this[int i]
{
    get { return getVal(i); }
    set { setVal(i, value); }
}

在XAML中:

<!-- If MemoryTable instance is property of current data context -->
<TextBox Text="{Binding MyMemoryTable[1]}" />

<!-- If MemoryTable instance itself is current data context -->
<TextBox Text="{Binding [1]}" />

我能想到几种不同的方法,但我不是特别喜欢其中的任何一种。

一种方法是将属性实现为索引器:

public float this[int index]
{
    get { return getVal(index); }
    set { setVal(index, value); }
}

您需要添加范围检查,因为有人可能会尝试这样做 myObject[7],这是不允许的。您可以绑定到 WPF 中的索引器。这样 可能 起作用。但这确实让 class 的消费者承担了责任,因为他们不会获得属性的智能感知(因为它只是一个不可或缺的参数)。

另一个选项会涉及一些反射技巧,以获取正在设置的 属性 的名称,并使用它来确定将哪个值传递给 getVal/setVal。但这至少有反射和字符串解析,感觉……不对。但这类似于使用 C# 6 中的 CallerMemberNameAttributenameof 运算符。