C #: Is it possible to implement a protected internal abstract in an abstract class?

What do I need to change in my abstract database so that implementations do not have to implement BOTH methods when only one is required in any given scenario? My example:

internal abstract class BaseBar<T> where T : BaseThing { protected internal abstract T DataFromXmlElements(IEnumerable<XmlNode> nodes); protected internal abstract T DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames); } class FooBarMapper : BaseBar<FooData> { protected internal override SforceObjectValueData DataObjectFromXmlElements(IEnumerable<XmlNode> nodes) { throw new NotImplementedException(); } protected internal override FooData DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames) { FooData o = new FooData { bar1 = bar1, bar2 = bar2 }; return o; } } 

Greetings.

edit: The design is strange / bad / stupid I know ... I work with outdated code, and time on my side is not for refactoring now. I am trying to add a second method with an array of strings.

+4
source share
9 answers

You can make one or both virtual and provide default implementations that call the others with default parameters (or without passing values, depending on how you placed it).

However, I suspect that your design may really require a bit more rethinking, because callers will most likely have a link to the base (your abstract class) and will not know that they invoke a specific derived version, in which case the caller must always be free to call the method that he likes.

+1
source

Maybe this will work for you?

 internal abstract class BaseBar<T> where T : BaseThing { protected internal abstract T DataFromXmlElements(IEnumerable<XmlNode> nodes, params string[] fieldNames); } 
+3
source

You can also encapsulate the parameters for DataFromXmlElements in the class, and then carefully examine the contents of the class when writing the implementation ...

+2
source

I assume that you will need 2 or 3 abstract classes to achieve this.

 public interface BaseBar1<T> // does one public interface BaseBar2<T> // does the other public interface BaseBar3<T> // does both 

you can use optional parameter

 internal abstract class BaseBar<T> where T : BaseThing { protected internal abstract T DataFromXmlElements( IEnumerable<XmlNode> nodes, string[] fieldNames); } class FooBarMapper : BaseBar<FooData> { protected internal override FooData DataFromXmlElements( IEnumerable<XmlNode> nodes, [Optional] string[] fieldNames) { if (fieldNames == null) // skip stuff else // do stuff } 

Read more about optional attribute .

+1
source

An absolute member MUST be implemented, so I think there is no way.

Another solution would be to define two interfaces, each of which contains one of the elements for implementation. Implementing classes can then implement one or both of the interfaces.

For instance:

 public interface BaseBarA<T> where T : BaseThing{ protected internal abstract T DataFromXmlElements(IEnumerable<XmlNode> nodes); } public interface BaseBarB<T> where T : BaseThing{ T DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames); } 
+1
source

It’s not really clear what you hope to do. What do you expect if the first method is called? Depending on what you expect, you can force the parent abstract class to implement the first method based on the assumption that the second is implemented:

 protected internal T DataFromXmlElements(IEnumerable<XmlNode> nodes) { return DataFromXmlElements(nodes, null); } 
+1
source

Impossible.

However, you can have only one abstract inner base class, and then two abstract classes (each with one abstract method).

Finally, you get a working class from EITHER from abstract classes and thus implement the corresponding single method.

This "will" work, but the bigger question is "should" do you do this? I think you can review your implementation.

+1
source

Either virtual implementations by default, as Colin Mackay said, or use interfaces and an explicit implementation to stop methods that are called externally.

 internal interface IBaseBar1<T> where T : BaseThing { T DataFromXmlElements(IEnumerable<XmlNode> nodes); } interface IBaseBar2<T> where T : BaseThing { T DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames); } class FooBarMapper : IBaseBar2<FooData> { FooData IBaseBar2<FooData>.DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames) { FooData o = new FooData { bar1 = bar1, bar2 = bar2 }; return o; } } 
+1
source

You cannot do this. The only option is to reorder your classes.

0
source

All Articles