Override virtual or abstracts with derived return types
-
Hi all, maybe someone can explain me, why this doesn't work in C#. Do i missed something, or is it a stupid idea to extend a return type of an override?
public class Class_a
{
Stream _something;public virtual Stream Property { get { return \_something; } set { \_something = value; } } } public class Class\_b : Class\_a { FileStream \_something; public override FileStream Property { get { return \_something; } set { \_something = value; } } }
Thanks & Regards, Johannes
-
Hi all, maybe someone can explain me, why this doesn't work in C#. Do i missed something, or is it a stupid idea to extend a return type of an override?
public class Class_a
{
Stream _something;public virtual Stream Property { get { return \_something; } set { \_something = value; } } } public class Class\_b : Class\_a { FileStream \_something; public override FileStream Property { get { return \_something; } set { \_something = value; } } }
Thanks & Regards, Johannes
Hello, You are trying to override the property 'Property' in derived class and you are trying to change the return type of the property, which is not allowed in the C#. In C#.Net it is mandatory to keep the signature of method/property you want to override in the derived class. Thanks, Rahul Kulkarni
-
Hi all, maybe someone can explain me, why this doesn't work in C#. Do i missed something, or is it a stupid idea to extend a return type of an override?
public class Class_a
{
Stream _something;public virtual Stream Property { get { return \_something; } set { \_something = value; } } } public class Class\_b : Class\_a { FileStream \_something; public override FileStream Property { get { return \_something; } set { \_something = value; } } }
Thanks & Regards, Johannes
-
As explained, its not possible but its not such a stupid idea. Ive tried a similar thing once or twice and found frustration.
-
Hello, You are trying to override the property 'Property' in derived class and you are trying to change the return type of the property, which is not allowed in the C#. In C#.Net it is mandatory to keep the signature of method/property you want to override in the derived class. Thanks, Rahul Kulkarni
Hi Rahul, thanks! I understand that i'm not allowed to change the return type. But i thought it should be allowed to extend it. So from the perspective of 'Class_a' the return type will always be "Stream". I know that i could use 'new' instead of 'override', but that wouldn't be the same and won't work with abstracts. This rule doesn't make sense to me. regards, Johannes
-
Well in your example, even if you return a
FileStream
from a method whose return type isStream
the calling code can cast it to its actual type (FileStream). However this is, like most things, an architectural question where a different approach altogether is usually the most elegant solution. edit: Generics can sometime help here example coming.... -
Hi all, maybe someone can explain me, why this doesn't work in C#. Do i missed something, or is it a stupid idea to extend a return type of an override?
public class Class_a
{
Stream _something;public virtual Stream Property { get { return \_something; } set { \_something = value; } } } public class Class\_b : Class\_a { FileStream \_something; public override FileStream Property { get { return \_something; } set { \_something = value; } } }
Thanks & Regards, Johannes
Here's an elegant generics solution to your problem
public class StreamWrapper<T> where T : Stream
{
private T stream;public T Stream { get { return this.stream; } set { this.stream = value; } }
}
public class FileStreamWrapper : StreamWrapper<FileStream>
{
public FileStreamWrapper()
{ }
}When you instantiate FileStreamWrapper, its Stream property is correctly typed as FileStream.
FileStreamWrapper fsw = new FileStreamWrapper();
fsw.Stream = new FileStream(...); -
Well in your example, even if you return a
FileStream
from a method whose return type isStream
the calling code can cast it to its actual type (FileStream). However this is, like most things, an architectural question where a different approach altogether is usually the most elegant solution. edit: Generics can sometime help here example coming....I'm facing this problem in several situations and i'm pretty sure this is an architectural question. This would be a good sample: There is a mask with a persons list and some search fields. I have a ViewModel class which provides the data (List) and the filter object (PersonFilter) where the search fields are bound to (WPF). Later i want to build a customers mask. Where the Customer class is an extension of Person and the CustomerFilter an extension PersonFilter. So i would love to extend my ViewModel, but i cannot override my Filter Property. Even if i'm sure that there won't be a solution, which let me do it this way. I thought it is time time to ask here. Thanks and regards, Johannes
-
Here's an elegant generics solution to your problem
public class StreamWrapper<T> where T : Stream
{
private T stream;public T Stream { get { return this.stream; } set { this.stream = value; } }
}
public class FileStreamWrapper : StreamWrapper<FileStream>
{
public FileStreamWrapper()
{ }
}When you instantiate FileStreamWrapper, its Stream property is correctly typed as FileStream.
FileStreamWrapper fsw = new FileStreamWrapper();
fsw.Stream = new FileStream(...);While your solution if FAR better, the OP could also declare the property as new instead of override.
public class Class_a { public virtual Stream Property { get; set; } } public class Class_b : Class_a { public new FileStream Property { get; set; } }
"Simplicity carried to the extreme becomes elegance."
-Jon Franklin -
While your solution if FAR better, the OP could also declare the property as new instead of override.
public class Class_a { public virtual Stream Property { get; set; } } public class Class_b : Class_a { public new FileStream Property { get; set; } }
"Simplicity carried to the extreme becomes elegance."
-Jon FranklinThe easiest way to deal with this is to keep the type declaration of the base class property and cast to the actual type when working with the derived class. You can also consider whether you're going to need any of the functionality specific to
FileStream
. IfStream
has all the functionality you need, then don't even worry about casting. I believe you may be able to do this with an Interface if you explicityly implement the interface item. Here's an example that works, but there's some trickery with an interface where you can have an explicit implementation of the interface defined that accesses the base class property and then a normal property of the same name that provides a different return type. Note that I had to implement the interface in both classes and also inClass_b
I had to specifically cast to and from the different stream types. This is because even thoughClass_a
implements the interface, I want to provide an explicit implementation inClass_b
, so I have to implement it also inClass_b
to do this. When you run this,Class_b.Property
returns typeFileStream
whileClass_a.Property
returns typeStream
.using System;
using System.Collections.Generic;
using System.Text;
using System.IO;namespace TestClass_a
{
public interface IStream
{
Stream Property { get; set; }
}public class Class\_a : IStream { private Stream \_stream = null; public Stream Property { get { return \_stream; } set { \_stream = value; } } } public class Class\_b : Class\_a, IStream { public FileStream Property { get { return (FileStream)base.Property; } set { base.Property = (Stream)value; } } #region IStream Members Stream IStream.Property { get { return base.Property; } set { base.Property = value; } } #endregion } class Program { static void Main(string\[\] args) { Class\_a a = new Class\_a(); a.Property = new MemoryStream(); Class\_b b = new Class\_b(); b.Property = File.Open("C:\\\\test.txt", FileMode.OpenOrCreate); Class\_a b2 = b; bool canRead = b2.Property.CanRead; } }
}
Keep It Simple Stupid! (KIS
-
The easiest way to deal with this is to keep the type declaration of the base class property and cast to the actual type when working with the derived class. You can also consider whether you're going to need any of the functionality specific to
FileStream
. IfStream
has all the functionality you need, then don't even worry about casting. I believe you may be able to do this with an Interface if you explicityly implement the interface item. Here's an example that works, but there's some trickery with an interface where you can have an explicit implementation of the interface defined that accesses the base class property and then a normal property of the same name that provides a different return type. Note that I had to implement the interface in both classes and also inClass_b
I had to specifically cast to and from the different stream types. This is because even thoughClass_a
implements the interface, I want to provide an explicit implementation inClass_b
, so I have to implement it also inClass_b
to do this. When you run this,Class_b.Property
returns typeFileStream
whileClass_a.Property
returns typeStream
.using System;
using System.Collections.Generic;
using System.Text;
using System.IO;namespace TestClass_a
{
public interface IStream
{
Stream Property { get; set; }
}public class Class\_a : IStream { private Stream \_stream = null; public Stream Property { get { return \_stream; } set { \_stream = value; } } } public class Class\_b : Class\_a, IStream { public FileStream Property { get { return (FileStream)base.Property; } set { base.Property = (Stream)value; } } #region IStream Members Stream IStream.Property { get { return base.Property; } set { base.Property = value; } } #endregion } class Program { static void Main(string\[\] args) { Class\_a a = new Class\_a(); a.Property = new MemoryStream(); Class\_b b = new Class\_b(); b.Property = File.Open("C:\\\\test.txt", FileMode.OpenOrCreate); Class\_a b2 = b; bool canRead = b2.Property.CanRead; } }
}
Keep It Simple Stupid! (KIS