views:

205

answers:

6

According to this question it seems like you can do this for Methods. What I want to know is why it doesn't work when I try it with properties.

public class Foo
{
    public virtual object Value
    {
        get;
        set;
    }
}

public class Foo<T> : Foo
{
    public override object Value
    {
        get
        {
            return base.Value;
        }
        set
        {
            base.Value = (T)value; //inject type-checking on sets
        }
    }

    public new T Value
    {
        get { return (T)base.Value; }
        set { base.Value = value; }
    }
}

Error message from C# 4.0 RC1

Error 1 The type 'ClassLibrary1.Foo' already contains a definition for 'Value' ClassLibrary1\Class1.cs 31 22 ClassLibrary1

+4  A: 

You can't have two properties using the same name. This is not allowed in C#. The only exception to this is indexers, since, in the case of an indexer, the signature changes by the index type.

You cannot make an overload for a method that only differs by the return type. A property with a single name is basically prohibited by the same rule, since it is internally a pair of methods with no argument for the get accessor.

Reed Copsey
+1 I don't know how I can tell for sure but this seems like it is probably the right answer - the same rule doesn't hit methods because of method overloading etc.
Tim Lovell-Smith
@Tim: Read the last paragraph here: http://msdn.microsoft.com/en-us/library/aa691131(v=VS.71).aspx The same rule applies to properties
Reed Copsey
A: 

You have two definitions of the same property Value one defined by override ... and one by new. The return type is not distinguishing feature in a method signature, i.e. if the signature only differs in the return type the signature is considered the same. So, use override or new.

In your case you could use new instead of override to achive the goal. However, when using new you always must consider that the implementation excecuted depends on the type you calling the method on. I.e.

var foo = new Foo();
var foo_ = new Foo<string>();

foo.Value            // calls the implementation on Foo 
foo_.Value           // calls the implementation on Foo<T>
((Foo) foo).Value    // calls the implementation on Foo
Obalix
Yes that is all exactly the behavior I want. The interesting one that I want is: ((Foo) foo_).Value // calls the implementation on Foo<T>
Tim Lovell-Smith
Strictly speaking, the override doesn't need a name. It only needs some method of being associated to the right v-table slot. Unfortunately, C# only makes that association using the name (C++/CLI and I believe also MSIL have ways to explicitly make the association).
Ben Voigt
+3  A: 

You could do this if you do something like the following...

public interface IFoo<T>
{
    T Value { get; set; }
}

public class Foo<T> : Foo, IFoo<T>
{
    T IFoo.Value
    {
        get { return (T)base.Value; }
        set { base.Value = value; }
    }
}

The only thing with this is that when you reference you have to be using the interface type... i.e.

   IFoo<int> myfoo = new Foo<int>();
   int result = myFoo.Value;    //This will give you the typed version

   Foo<int> myfoo = new Foo<int>();
   int result = myFoo.Value;    //This will give throw an exception
anthonyv
I had to come up with a slightly different workaround in fact because my base class is not abstract, it is really supposed to work with object (it only stops working with object when you construct it with the type parameter).
Tim Lovell-Smith
A: 

You can get at this with an interace.

public interface IFoo
{
    object Value { get; set; }
}

public class Foo<T> : IFoo
{
    object _value = null;
    object IFoo.Value
    {
        get { return _value; }
        set { _value = value; }
    }

    public T Value
    {
        get;
        set;
    }
}
Anthony Pegram
A: 

The underlying problem is that it can never be known which property to use.

for example,

Foo<int> s = new Foo<int>();

s.Value = "hmmm";

So which property should be used? int derives from object and also meets the generic property version's constraints as well.

bic
My intent is that that will throw (if you can get it to compile :-))
Tim Lovell-Smith
It wouldn't be ambiguous at all. The overridden virtual property would be used for polymorphic access through a base class reference, the new property would be used for access through a reference statically-typed with the derived class (or any of its descendants). One way to accomplish that is using an intermediate base class to provide the overriding definition.
Ben Voigt
+1  A: 

C++/CLI can do it even if C# can't. In C++/CLI you can explicitly say which method is being overridden, so the names don't have to match.

Ben Voigt
+1 Interesting!
Tim Lovell-Smith