C#中的通用属性

55

可能是重复问题:
创建通用属性

我不太确定如何做到这一点,但我想创建一种特殊类型的属性,在泛型类型上定义,它会在getset时执行特定任务。 例如,当编写以下内容时:

MyProp<String> name;

预定义的 getset 将在字符串值上执行。

如何实现呢?

谢谢!


4
我不确定我理解这个问题。 - user47589
1
为什么你需要泛型?你能否提供一个实际的例子,说明你想要做什么以及为什么要在不同类型上进行操作? - Dave
我也不明白。MyProp<string> name { get { return DoCustomGet(); } { set { DoCustomSet(value); } } 这样行不行? - Jaxidian
3
在C++中,这被称为“模板特化”。在.NET泛型中不可用。 - Hans Passant
6个回答

104
您可以像这样创建一个通用类:
public class MyProp<T>
{
    private T _value;

    public T Value
    {
        get
        {
            // insert desired logic here
            return _value;
        }
        set
        {
            // insert desired logic here
            _value = value;
        }
    }

    public static implicit operator T(MyProp<T> value)
    {
        return value.Value;
    }

    public static implicit operator MyProp<T>(T value)
    {
        return new MyProp<T> { Value = value };
    }
}

然后在类中像这样使用它:

class SomeClass
{
    public MyProp<int> SomeProperty { get; set; }
}

隐式操作符意味着您不需要显式设置或获取 MyProp Value 属性,但可以编写代码以更加“自然”的方式访问该值:
SomeClass instance = new SomeClass();
instance.SomeProperty = 32;
int someInt = instance.SomeProperty;

我认为这里缺少考虑“..创建一种特殊类型的属性,在获取和设置时执行特定任务..”- 但由于这个问题真的不清楚,所以我可能是错的。 - Benjamin Podszun
@Benjamin:是的,这个问题有点不清楚,但这就是在我的代码示例中使用“插入所需逻辑”的注释的地方。您可以放入一些逻辑,无论为哪个属性执行getter或setter,都会执行该逻辑。 - Fredrik Mörk
哇,我完全错过了整个画面。我真的不喜欢隐式操作符,但是 - 我想你回答得很好。+1。 - Benjamin Podszun
1
+1 表示你已经按照我所描述的完成了任务。 - John Fisher
优美的解决方案。假设您不需要属性采用不同类型的通用方面,但您有一组属性,其中get和set都将采用相同的代码。您仍然可以创建一个类,其中包含如下所示的两个隐式运算符。这就是我要找的。谢谢!这避免了:public class Mango { public String property1 { get { myProp1.callGet(); } } public String property2 { get { myProp2.callGet(); } }} - froggythefrog
太棒了!一开始我不明白它是如何工作的,因为我以为Value属性的get和set方法被映射到SomeProperty的getter和setter中,然后我注意到它们在隐式引用中被引用。 - rrrrrrrrrrrrrrrr

5
您不能以这种方式“更改”属性语法。您可以做的是:
class Foo
{
    string MyProperty { get; set; }  // auto-property with inaccessible backing field
}

一个通用版本可能是这样的:

class Foo<T>
{
    T MyProperty { get; set; }
}

4

好的,我来翻译。你想要的是这样的东西:如果你像这样声明一个“属性”:

更新:我现在非常确定Fredrik Mörk回答了你的问题并给出了解决方案。我对这个想法不是很满意,但它似乎恰好回答了我从你的问题中理解到的内容。

public class PropertyFoo {
  public MyProp<String> Name;
}

这最终变成

public class PropertyFoo {
  public string Name {
    get { /* do predefined stuff here */ }
    set { /*other predefined stuff here */ }
  }
}

不可能实现且也不是一个属性。在你的IDE中寻找模板/片段支持。


+1 最合乎逻辑的结论。 - leppie

2

您只需按照通用类型的正常方式声明该属性:

public MyType<string> PropertyName { get; set; }

如果你想调用预定义的方法在get或set中执行某些操作,那么需要实现属性的getter/setter来调用这些方法。


你也可以使用未绑定的泛型类型声明属性,这会让事情更有趣:public MyType<T> PropertyName { get; set; }。如果你实现了getter/setter,值的类型将是T,并且会随着它的使用而变化。 - dthorpe

2

您需要创建一个名为MyProp的通用类。然后,您将需要添加隐式或显式的转换运算符,以便您可以获取和设置该值,就像它是在通用类型参数中指定的类型一样。这些转换运算符可以执行您所需的额外工作。


我认为仅使用强制转换操作符无法解决这个问题,还需要赋值运算符,但赋值运算符是不可重载的。 - Tim Mahy
@Tim:强制类型转换可以双向使用。当将一个字符串分配给MyProp<string>时,如果存在隐式的强制类型转换运算符,则会使用它。 - John Fisher
是的,但开发人员仍然可以使用MyProp<string>值设置属性,而不会被拦截... - Tim Mahy
@Tim:好的,但这不是他想要的使用模式。按照预期的、直接的、简单的、正常的方式使用它不会有这个问题。 - John Fisher

1
public class MyProp<T>
{
...
}

public class ClassThatUsesMyProp
{
public MyProp<String> SomeProperty { get; set; }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接