Read-only interface without requiring body in abstract class? - c#

I'd like to be able to create a read-only property in an interface that is writable in the instantiated class, but I'm having problems if the inheritance goes through an abstract class:
interface IFoo {
string Foo { get; }
}
abstract class Bar : IFoo {
}
class Baz : Bar {
public string Foo { get; private set; }
}
This gives me an error Bar does not implement interface member IFoo.Foo. Is there any way to circumvent this? I want the ultimately-instantiated class to determine the visibility of the setter.

You need to implement it abstract:
abstract class Bar : IFoo
{
public abstract string Foo { get; }
}
However, it doesn't look like when you do this that you can choose to override the visibility in the Baz class.
The best you can do is to use a backing field in the derived class:
class Baz : Bar
{
private string _foo;
public override string Foo
{
get { return _foo; }
}
}
This answer on a duplicate question goes into more detail on the why. The problem stems from the fact that property getters and setters are abstract, rather than the property itself.

Related

How do Auto-Implemented properties work in C# interfaces?

If I declare Auto-Implemented properties in C# classes, then public string Property { get; set; } becomes:
private string _property;
public string get_Property() {
return _property;
}
public void set_Property(string value) {
_property = value;
}
which includes a private field string _property.
If I create an interface, I am allowed to use Auto-Implemented properties like so:
string Property { get; set; }
Why can I declare Auto-Implemented properties inside Interface, but I can't use the longer, more verbose syntax that declares private fields? I am aware of the definition that says:
An interface contains only the signatures of methods, properties, events or indexers
Is the private field in interfaces not generated the same as in classes? Is it generated at all?
Why can I declare Auto-Implemented properties inside Interface
They aren't auto-implemented, it's just that the syntax of a property declaration is identical to the syntax for an auto-implemented property definition.
This:
interface IFoo
{
String Bar { get; set; }
}
Means: "IFoo has a public[1] String property named Bar which has a getter and a setter."
This:
class Foo
{
String Bar { get; set; }
}
Means: "Foo has a private[2] String property named Bar which has a getter and a setter, and the getter and setter are both auto-generated by the compiler and operate on a hidden instance field.
Note that the syntax used in the interface is unrelated to the syntax used by implementation in the class or struct. So given the same IFoo as above...
interface IFoo
{
String Bar { get; set; }
}
...we can have:
// Using auto-implemented property:
class Foo2 : IFoo
{
public String Bar { get; set; }
}
// Using explicit backing field:
class Foo3 : IFoo
{
private String bar;
public String Bar
{
get { return this.bar; }
set { this.bar = value; }
}
}
// Using expression-body syntax with a backing field:
class Foo4 : IFoo
{
private String bar;
public String Bar
{
get => this.bar;
set => this.bar = value;
}
}
// Using explicit interface implementation with a backing field:
class Foo5 : IFoo
{
private String bar;
String IFoo.Bar
{
get { return this.bar; }
set { this.bar = value; }
}
}
// You can also use explicit interface implementation with an auto-implemented property:
class Foo6 : IFoo
{
String IFoo.Bar { get; set; }
}
// However, if it's a getter-only property you won't be able to set a property value in the constructor - but you can initialize it inline:
interface IReadOnlyFoo
{
String Bar { get; }
}
class Foo7 : IReadOnlyFoo
{
String IReadOnlyFoo.Bar { get; } = "foo"; // ok
}
class Foo8 : IReadOnlyFoo
{
public Foo8()
{
this.Bar = "foo"; // <-- Error. `Bar` is not a member of `this`.
// You also can't cast `(IReadOnlyFoo)this` because `IReadOnlyFoo` does not contain a setter.
}
String IReadOnlyFoo.Bar { get; }
}
Is the private field in interfaces not generated the same as in classes
Interfaces don't have fields, interfaces only have virtual methods (or rather: an interface can be thought-of as a single vtable). Note that internally: properties and events are also fundamentally virtual methods (also note that while internally they're virtual calls, implemented interface methods are not automatically virtual (in the C# sense) in that a subclass of an interface implementation cannot arbitrarily override any interface member[3].
Also not to be confused with "Default interface implementations" in C# 8.0 which a more akin to extension methods than treating interfaces as classes, because interfaces still cannot have fields.
You should also familarise yourself with C#'s expression-bodied member syntax (though it isn't used much for property-setters):
class Foo2
{
String bar; // this is a private instance field
String Bar // this is a private instance property
{
get => this.bar;
set => this.bar = value;
}
}
[1] Disregarding Explicit Interface Implementation, of course.
[2] Class members are private by default if they don't have an explicit access-modifier.
[3] Subclasses can reimplement an interface which will have the effect of overriding any virtual-calls to that interface member, but only if the member is accessed through an interface reference rather than through an object reference to the class's supertype.

How to downcast this to the base class?

I have this class hierarchy:
public abstract class AClass : SomeFrameworkClass {
[WorkOnThisProperty(With.Some.Context)]
private MyObject MyProperty { get; set; }
public override void OnSomethingHappened() {
ExternalFramework.WorkOn(this);
}
}
public class BClass : AClass {
// ... Snip ...
}
ExternalFramework is operating on this: an instance of BClass but i need it to operate on this as an instance of AClass because ExternalFramework only works on the type of the object passed in and does not go up the inheritance hierarchy. How can i downcast this into AClass so ExternalFramework can actually detect MyProperty?
I've tried casting this to object and then to AClass, and casting it directly to AClass but as the cast is unnecessary it doesn't seem to run. What can i do about this?
EDIT: ExternalFramework is Cheeseknife. I am trying to inject a couple views into a base fragment class that has all the reusable logic while child fragment classes implement some specific behaviour tuning.
The problem is that all private members of a class can only be accessed inside of the same class.
With this code:
class A { private string Property { get; set; } }
class B : A { public string Proxy => Property; }
We'll get compilation error because class B cannot access private property from class A, but if change keyword to protected :
class A { protected string Property { get; set; } }
It should work.

Reducing generic parameters

I'm trying to get an inheritance hierarchy of generics working, and I'm running into a bit of a problem.
Here's an example:
interface IFoo {}
interface IFoo<T> : IFoo
{
T Data { get; }
}
class Foo : IFoo<int> { public int Data { get; set; } }
interface IBar {}
class Bar : IBar { }
abstract class LayerOne<T_FOO, T_BAR> where T_FOO : IFoo where T_BAR : IBar {}
abstract class LayerTwo<T_FOO> : LayerOne<T_FOO, Bar> where T_FOO : IFoo, new()
{
protected T_FOO _foo = new T_FOO();
public void Test1() { _foo.Data.Dump();} // Compiler error
}
class LayerThree : LayerTwo<Foo>
{
public void Test2() { _foo.Data.Dump();}
}
I'm trying to get access to .Data in the LayerTwo class. Clearly, since IFoo doesn't have that property, it's going to error. However, if I change they type of T_FOO to IFoo<T>, then I have to define it and LayerThree as:
abstract class LayerTwo<T_FOO, T> : LayerOne<T_FOO, Bar> where T_FOO : IFoo<T>, new()
{
protected T_FOO _foo = new T_FOO();
public void Test1() { _foo.Data.Dump();}
}
class LayerThree : LayerTwo<Foo, int>
{
public void Test2() { _foo.Data.Dump();}
}
But the intent of the concrete Foo implementation is that it already knows it's implementing IFoo<int>. Is there any way I can get LayerTwo to know about the Data property without requiring it to be looked up from Foo and added to LayerThree's definition?
What I'd love is:
class LayerThree : LayerTwo<Foo> // Automatically realizes that the second generic is int
{
public void Test2() { _foo.Data.Dump();}
}
Update: As it turns out, I was actually trying to implement two contradictory things in my code. The actual LayerTwo was trying to keep T_FOO generic, but also created an (abstract) method which required a specific type from IFoo<T>.
So the solution I'm going with is just to use an interface which inherits from IFoo<T> and specifies the type, but I'm accepting Ondrej Tucny's answer, since it did solve the problem I asked about.
This is exactly the same situation as with IEnumerable / IEnumerable<T>. Your weakly typed interface IFoo needs to provide a weakly typed Data:
public interface IFoo
{
object Data { get; }
}
public interface IFoo<T> : IFoo
{
new T Data { get; }
}
then in the implementation one of the will be explicit to favor strongly typed access:
public class IntFoo : IFoo<int>
{
public int Data { get { return -1; } }
object IFoo.Data { get { return Data; } }
}
Now you have access to Data in either case, although when the actual type T is unknown, you have to live with an object.

What's wrong in this interface use?

Suppose to have an interface like this:
interface MyInterface
{
public string AProperty { get; set;}
public void AMethod ()
}
This interface is used inside another interface:
interface AnotherInterface
{
public MyInterface member1 { get; set; }
public int YetAnotherProperty {get; set;}
}
Now suppose to have two classes, one that implements each of the interfaces.
class MyInterfaceImpl : MyInterface
{
private string aproperty
public string AProperty
{
//... get and set inside
}
public void AMethod ()
{
//... do something
}
}
And at last:
class AnotherInterfaceImpl : AnotherInterface
{
private MyInterfaceImpl _member1;
public MyIntefaceImpl member1
{
//... get and set inside
}
...Other implementation
}
Why does the compiler complain that AnotherInterfaceImpl does not implement MyInterface?
I understand it is a very basic question... but I need to serialize to xml AnotherInterfaceImpl and I cannot do that if member1 is of type MyInterface.
Your class AnotherInterfaceImpl is not actually implementing all members of AnotherInterface. The public property AnotherInterfaceImpl.member1 must have type MyInterface, not MyInterfaceImpl.
Note that this restriction only applies to the public property. The private field AnotherInterfaceImpl._member1 can still be of type MyInterfaceImpl, because MyInterfaceImpl implements MyInterface.
Why the compiler complains that AnotherInterfaceImpl does not implement MyInterface?
Because it doesn't implement it. It has a member that implements it.
That is like saying "my customer object has an orders (list) property; how come my customer isn't a list?"
If you had either:
interface AnotherInterface : MyInterface
or
class AnotherInterfaceImpl : AnotherInterface, MyInterface
then it would be true to say that AnotherInterfaceImpl implemented MyInterface.
you need to "explicitly" type your members as the interface defines them.
class AnotherInterfaceImpl : AnotherInterface
{
private MyInterfaceImpl _member1;
public MyInteface member1
{
get{ return _member1;}
set{ _member1 = value;}
}
...Other implementation
}

How to automatically copy a property declaration to base class

I have a property A in all subclasses of base class Base.
How can I generate an abstract property definition of property A into base class Base?
I know ReSharper's refactoring Pull Members Up, but that moves the property to base class.
I need an abstract property in base class and a overriding properties in all sub classes. Is there a refactoring in Visual Studio or in ReSharper that can do it automatically for me?
There is a checkbox "Make abstract" for that in ReSharper Pull Members Up dialog :
I'm not sure Resharper can move up and create an abstraction as you want automatically, but you can atleast define it manually like this
In abstract class:
public abstract double A
{
get;
}
In Sub class:
public override double A
{
get
{
return 3.141;
}
}
It might be a clearner design to define a new Interface (or use an existing one) and define the property in the interface. That way, your existing subclasses won't have to use override.
public interface IInterface {
string MyProperty { get; }
}
public class Class : IInterface {
public string MyProperty { get; set; }
}
public abstract class AbstractClass {
public abstract string Value { get; }
}
public class ConcreteClass : AbstractClass {
private string m_Value;
public override string Value {
get { return m_Value; }
}
public void SetValue(string value) {
m_Value = value;
}
}
I hope this will be helpful to you.

Categories