55

Possible Duplicate:
Making a generic property

I'm not quite sure how to do that, but what I would like to do is to create a special type of property that will perform specific tasks at the get and set, and will be defined on generic type. For example, when writing this:

MyProp<String> name;

a pre-defined get and set will be performed on the string value.

How can that be done?

Thanks!

Community
  • 1
  • 1
rachmos
  • 553
  • 1
  • 5
  • 4
  • 4
    I'm not sure I understand the question. –  Apr 06 '10 at 18:16
  • 1
    why do you need generics for this? can you post an example of what you actually want to do, and why you want to do it on various types? – Dave Apr 06 '10 at 18:17
  • I also don't understand. Would `MyProp name { get { return DoCustomGet(); } { set { DoCustomSet(value); } }` not work? – Jaxidian Apr 06 '10 at 18:18
  • 3
    It is called "template specialization" in C++. Not available in .NET generics. – Hans Passant Apr 06 '10 at 18:48

6 Answers6

104

You can make a generic class like this:

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 };
    }
}

...then use it in a class like so:

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

The implicit operators means that you do not need to explicitly set or get the Value property of MyProp, but can write code to access the value in a more "natural" way:

SomeClass instance = new SomeClass();
instance.SomeProperty = 32;
int someInt = instance.SomeProperty;
Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • I think this is missing to take "..to create a special type of property that will perform specific tasks at the get and set.." into account - but since this question is really unclear I might be wrong. – Benjamin Podszun Apr 06 '10 at 18:38
  • @Benjamin: yes, the question is a bit unclear, but that is where the `insert desired logic here` comments come into the picture in my code sample. You could put in some logic that will be performed whenever the getter or setter is invoked, regardless of which property it is done for. – Fredrik Mörk Apr 06 '10 at 18:43
  • Whoa, I completely missed to see the whole picture. I'm really no friend of implicit operators, but - I guess you answered the question just fine. +1. – Benjamin Podszun Apr 06 '10 at 18:54
  • 1
    +1 for writing out what I had described. – John Fisher Apr 06 '10 at 20:10
  • Beautiful solution. So let's say you did not need the generic aspect where your properties take different types, but you have this set of properties where get and set are all going to take the same code. You could still create a class with the two implicit operators as shown here. This is what I was looking for. Thanks! This avoids: public class Mango { public String property1 { get { myProp1.callGet(); } } public String property2 { get { myProp2.callGet(); } } } – froggythefrog Jul 20 '14 at 22:12
  • This is brilliant! At first I didn't get how it worked, because I thought the get and set methods of the Value property were somehow getting mapped to the getter and setter of SomeProperty - then I noticed they were being referenced in the implicits. – rrrrrrrrrrrrrrrr Aug 19 '17 at 15:06
5

You cannot 'alter' the property syntax this way. What you can do is this:

class Foo
{
    string MyProperty { get; set; }  // auto-property with inaccessible backing field
}

and a generic version would look like this:

class Foo<T>
{
    T MyProperty { get; set; }
}
H H
  • 263,252
  • 30
  • 330
  • 514
4

Okay, I'll bite. You want something like this: If you declare a "property" like this:

Update: I'm now pretty sure that Fredrik Mörk answered your question and gave a solution. I'm not really happy with the idea, but it seems to answer exactly what I understood from your question.

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

this ends up as

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

No. Not possible and not a property, really. Look for template/snippet support in your IDE.

Benjamin Podszun
  • 9,679
  • 3
  • 34
  • 45
2

You would need to create a generic class named MyProp. Then, you will need to add implicit or explicit cast operators so you can get and set the value as if it were the type specified in the generic type parameter. These cast operators can do the extra work that you need.

John Fisher
  • 22,355
  • 2
  • 39
  • 64
  • would not work I think with only the cast operators, one also would need the assignment operator which is not overloadable... – Tim Mahy Apr 06 '10 at 18:20
  • @Tim: Cast operators go both ways. When assigning a string to a MyProp, if there is an implicit cast operator, it would get used. – John Fisher Apr 06 '10 at 19:55
  • yes but a developer would still be able to set the property with a MyProp value without having it being intercepted.... – Tim Mahy Apr 07 '10 at 06:55
  • @Tim: Sure, but that's not the usage model he wanted. Using it in the expected, straightforward, simple, normal way would not have this issue. – John Fisher Apr 07 '10 at 14:39
2

You just declare the property the normal way using a generic type:

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

If you want to call predefined methods to do something in the get or set, implement the property getter/setter to call those methods.

dthorpe
  • 35,318
  • 5
  • 75
  • 119
  • You can also declare properties with unbound generic types, which makes things more fun: public MyType PropertyName { get; set; }. If you implement the getter/setter, the type of the value will be T and will vary with how it is used. – dthorpe Apr 06 '10 at 18:24
1
public class MyProp<T>
{
...
}

public class ClassThatUsesMyProp
{
public MyProp<String> SomeProperty { get; set; }
}
ileon
  • 1,508
  • 1
  • 18
  • 25