"Hiding" generic methods with nongeneric method in child class - c#

I have written some code and I'm curious as to whether or not there is a danger in what I'm doing that I'm unaware of.
I have tried searching and most of the questions I found dealt with how to make things generic which isn't my issue. I also looked in the C# spec for .net 4.5 under section 13.4.3 - Generic Methods and 7.5.2 in regards to Type inference and finally 7.5.2.12 Inferred return type and they don't really cover what I'm trying to do.
Basically I have a hierarchy of classes
public class SomeBaseClass { }
public class SomeClass : SomeBaseClass { }
public class AnotherClass : SomeBaseClass { }
public class BaseData
{
public SomeBaseClass mMember;
public BaseData() { }
public TType GetMember<TType>()
where TType : SomeBaseClass
{
return (TType)mMember;
}
}
public class Data : BaseData
{
public Data()
{
mMember = new SomeClass();
}
//Is this bad
public SomeClass GetMember()
{
return base.GetMember<SomeClass>();
}
}
The compiler doesn't complain because I'm not hiding the base class method. This is shown that intellisense lists them as two separate methods. I've written several tests which all behave the way I would expect them to and when looking at things like List<> there are instances of methods that have both a generic and nongeneric implementation (for example AsParallel from ParallelEnumerable) but the difference is that in this case both methods exist in the same class and take in a generic and nongeneric parameter respectively.
The tests I ran and showed work the way I would expect are listed below.
class Program
{
static void Main(string[] args)
{
BaseData lData = new Data();
Data lData2 = new Data();
//Call base method with type
SomeBaseClass lTest = lData.GetMember<SomeClass>();
//Cast and call derived method
SomeClass lTest2 = ((Data)lData).GetMember();
//Call base method with type and then cast
SomeClass lTest3 = (SomeClass)lData.GetMember<SomeBaseClass>();
//Call derived method directly
SomeClass lTest4 = lData2.GetMember();
//Throw InvalidCastException
SomeBaseClass lTest5 = lData2.GetMember<AnotherClass>();
}
}
The main reason for this is that I would like that any caller code doesn't have to know the generic type when the class itself already has this information. It's to avoid having to write
lData.GetMemberType<...>();
all over the place.
I apologize if this question is too broad or opinionated. Mostly I'm just wondering if there is anything in this scenario that wouldn't work the way I would think or have a hidden bug etc.

Your question is a little too vague to give a very good answer (what are you using this for? what is the purpose of this design?).
I don't think the name overlap is all that problematic, but it does seem like a symptom of a problematic design and a misuse of generics (all that casting should clue you in on that).
Ideally, your class itself should be generic, and you should use the generic type parameter throughout. That will save you from all the casting you are doing:
public class SomeBaseClass { }
public class SomeClass : SomeBaseClass { }
public class AnotherClass : SomeBaseClass { }
public class BaseData<TType> where TType : SomeBaseClass
{
protected TType mMember;
public BaseData() { }
public BaseData(TType member)
: this()
{
mMember = member;
}
public TType GetMember()
{
return mMember;
}
}
public class Data : BaseData<SomeClass>
{
public Data()
: base(new SomeClass())
{
}
// no need to implement GetMember(); base class has it covered
}

Related

Can I use recursive constraints to define a generic class

In one of my pet projects I have found myself using generics quite a lot and I'm wondering if it is possible to use recursive constraints in a generic class.
Let's imagine I have the following interface
public interface IAmSpecial {}
and the classes implementing it can each be handled by its own class
public class SpecialHandler<T> where T: IAmSpecial {}
I would like to define a class that is generic over any SpecialHandler
public class SpecialWrapperHandler<T> where T : SpecialHandler<SpecialT> where SpecialT: IAmSpecial
{
public SpecialWrapperHandler(T t){}
}
which doesn't compile. I can define the SpecialWrapperHandler class with the following signature
public class SpecialWrapperHandler<T> where T : SpecialHandler<IAmSpecial>
{
public SpecialWrapperHandler(T t){}
}
but then I cannot build it since any SpecialHandler implementation will close the generic value on one implementation of IAmSpecial. Also I cannot declare something like
public class SpecialWrapperHandler<SpecialHandler<T>> where T : IAmSpecial
So is it possible to have a C# construct that recurse generic constraints so I can my SpecialWrapperHandler? If so what construct should I use? And if not, why? A quick read of the generics chapter in the doc doesn't yield many answers...
Pass in a second type parameter for the handler. In that way you can type both parameters.
Like so:
public class SpecialWrapperHandler<H, T> where H : SpecialHandler<T> where T : IAmSpecial
{
public SpecialWrapperHandler(T t){}
}
Proof:
public class X : IAmSpecial { }
public class XHandler : SpecialHandler<X> { }
static void Main(string[] args)
{
X x = new X();
SpecialWrapperHandler<XHandler, X> v = new SpecialWrapperHandler<XHandler, X>(x);
}

Covariance Pattern for Abstract Classes

I'm realizing now that covariance is not available in abstract classes but is there anyway that I can utilize it here so that I can continue with this pattern.
Basically want the ability to create an instance of the first generic argument and pass the object which creates this object itself.
The below will fail at runtime because SpecialProcessor cannot be assigned to ProcessorBase with respect to generic types.
Appreciate any suggestions.
public class ProcessorUser<T> where T : ProcessorBase
{
public void ReceiveCommand()
{
Activator.CreateInstance(typeof (T), this);
}
}
public abstract class ProcessorBase
{
protected ProcessorBase(ProcessorUser<ProcessorBase> param)
{
}
}
public class SpecialProcessor : ProcessorBase
{
public SpecialProcessor(ProcessorUser<ProcessorBase> param)
: base(param)
{
}
}
Actually, from your less-than-complete code example, it's not clear at all a) what you are trying to do, and b) what "fails at runtime". You didn't show any code that calls the ReceiveCommand() method, so it's impossible to see in what way that code might fail.
That said, the usual way to gain access to variance in C# is through delegate or interface types. So you can declare a covariant interface to be implemented by ProcessorUser<T>, and then use that interface in the constructor declarations instead of the actual type. For example:
interface IProcessorUser<out T> where T : ProcessorBase
{
void ReceiveCommand();
}
class ProcessorUser<T> : IProcessorUser<T> where T : ProcessorBase
{
public void ReceiveCommand()
{
Activator.CreateInstance(typeof(T), this);
}
}
abstract class ProcessorBase
{
protected ProcessorBase(IProcessorUser<ProcessorBase> param)
{
}
}
class SpecialProcessor : ProcessorBase
{
private IProcessorUser<SpecialProcessor> _param;
public SpecialProcessor(IProcessorUser<SpecialProcessor> param)
: base(param)
{
_param = param;
}
public void ReceiveCommand() { _param.ReceiveCommand(); }
}
Note that I added the ReceiveCommand() method to the SpecialProcessor class just so I could see something execute at run-time. And that something does in fact work. But there's no way for me to know whether in your scenario, this is what you wanted to happen. You'd have to provide a good, minimal, complete code example that clearly shows what you are trying to do and what difficulty you are having doing it, if you want a clear, precise answer to that aspect of it.
(By the way, this really doesn't have anything to do with abstract classes. There's not even anything in your code example that is actually abstract, other than the class declaration itself, and the general principle applies to any class, not just abstract ones).

Returning child type in Parent class

public abstract class Base
{
public Base ClassReturn()
{
return this;
}
}
Is there possibility to return child type that invoked ClassReturn method?
I've done that in extension method:
public static T ClassReturn<T>(this T obj) where T : Base
{
return (T) obj.ClassReturn();
}
But I want to embeed it in Base class instead of extension method. Is there possibility to do that with generics?
I will copy my comment which describes what I want to achieve:
I need something similiar to builder pattern and I have different
classes that depending on previous operations do something else, now I
want to have a similiar functionality in every of them and when I use
it I lose object type. So my solution is either implement that
functionality multiple times in every class or create extension
method. But I always thought when it is possible to make extension
method for class then I can embeed that in class, but as I see it is
not possible.
Full example:
public class Child1 : Base
{
public Child1 Operation1()
{
Console.WriteLine("operation1");
return this;
}
}
public class Child2 : Base
{
public Child2 Operation2()
{
Console.WriteLine("operation2");
return this;
}
}
static void Main(string[] args)
{
Child1 ch = new Child1();
ch.Operation1().Operation1().ClassReturn().Operation1()
}
I can't use Operation1 after ClassReturn if I don't use extension method.
Try this one:
public abstract class Base<T> where T: Base<T>
{
public T ClassReturn
{
get { return (T)this; }
}
}
public class Child1 : Base<Child1>
{
}
public class Child2 : Base<Child2>
{
}
From your question and your comments, what you are trying to achieve is not possible directly from the type system. By returning an instance of Base you are specifically saying that all you are interested is that you have something that derives from Base, but that the specific class doesn't matter. Statically, the compiler no longer has the information it needs to perform a cast.
If you are trying to get the original type back statically, then you have to supply the information to the compiler, and in this case you can't guarantee that you have the correct information. In the example below, the instance is created from derived type A but attempted to be cast to derived type B through the extension, the compiler will allow the code to compile, but you'll get an exception at runtime.
public class A : Base { }
public class B : Base { }
public static class BaseExtensions
{
public static T GetAsT<T>(this Base base) where T: Base
{
return (T)base;
}
}
public static void Main()
{
Base obj = new A();
B b = obj.BaseAsT<B>(); // This compiles but causes an exception
}
You should look up the Liscov Substitution Principle to get information on how to properly work with base and derived classes in the system as a whole, and then write up a question dealing specifically with the result you are trying to achieve.

Force a child class to pass itself as the Generic parameter to the base class

I want to force my child classes to pass themselves as as the generic parameter to the parent class.
For example :
class BaseClass<T> where T: BaseClass
{
//FullClassName : Tuple [Save,Update,Delete]
Dictionary<string,Tuple<delegate,delegate,delegate>> dict = new Dictionary...;
static BaseClass()
{
RegisterType();
}
private static void RegisterType()
{
Type t = typeof(T);
var props = t.GetProperties().Where(/* Read all properties with the SomeCustomAttribute */);
/* Create the delegates using expression trees and add the final tuple to the dictionary */
}
public virtual void Save()
{
delegate d = dict[t.GetType().FullName];
d.Item1(this);
}
}
class ChildClass : BaseClass<ChildClass>
{
[SomeCustomAttribute]
public int SomeID {get;set;}
[SomeCustomAttribute]
public string SomeName {get; set;}
}
public class Program
{
public static void Main(string[] args)
{
ChildClass c = new ChildClass();
c.Save();
}
}
Obviously the above code won't compile. I'll restate : I want the child class to pass itself as the generic parameter and not any other child of BaseClass.
(The above code is kind of a psuedo code and will still not compile).
You can do this:
public class BaseClass<T> where T: BaseClass<T> { }
public class ChildClass : BaseClass<ChildClass> { }
But this doesn't force you to use ChildClass as the generic parameter. You could do this public class OtherChildClass : BaseClass<ChildClass> { } which would break the "coontract" that you want to enforce.
The direct answer is that if your accessing a static method then typeof(T) will give you the type for reflection.
However, there is probably better solutions than using reflection. Options:
1) Static constructor on the child class.
2) Abstract method declared in the base class.
I do not know the application, but I get concerned about my design if I feel like using a static constructor, I also get concerned if a base class needs to initialize the child class.
I suggest looking at injection as a solution rather than inheritance. It offers superior unit testing and often a better architecture.
More info (after initial post), this is my preferred solution:
public interface IRegesterable
{
void Register();
}
public class Widget : IRegesterable
{
public void Register()
{
// do stuff
}
}
public class Class1
{
public Class1(IRegesterable widget)
{
widget.Register();
}
}
Hope this helps
The ConcurrentDictionary is being used as a Set<Type>. We can check in the Set<Type> if the type has been initialized. If not we run RegisterType on the type.
public abstract class BaseClass
{
//Concurrent Set does not exist.
private static ConcurrentDictionary<Type, bool> _registeredTypes
= new ConcurrentDictionary<Type, bool>();
protected BaseClass()
{
_registeredTypes.GetOrAdd(GetType(), RegisterType);
}
private static bool RegisterType(Type type)
{
//some code that will perform one time processing using reflections
//dummy return value
return true;
}
}
public class ChildClass : BaseClass
{
}
There are several inefficiencies with this pattern though.
object.GetType() is pretty darn slow, and inefficient.
Even with the HashSet behavior, we are checking for initialization on each instanciation. Its as fast as I can get it, but its still pretty superfluous.

Java Inheritance Constraints

I am trying to port some code I wrote in C# to Java, but do not know all of the Java syntax yet. I also have no idea what this type of thing is called, so it is harder to search..I am calling it "inheritance constraints."
Basically, is there a java equivalent to this C# code:
public abstract class MyObj<T> where T : MyObj<T>, new()
{
}
Thanks.
Edit:
Is there any way to do this:
public abstract class MyObj<T extends MyObj<T>> {
public abstract String GetName();
public virtual void Test() {
T t = new T(); // Somehow instantiate T to call GetName()?
String name = t.GetName();
}
}
Not quite. There's this:
public abstract class MyObj<T extends MyObj<T>>
but there's no equivalent to the new() constraint.
EDIT: To create an instance of T, you'll need the appropriate Class<T> - otherwise type erasure will byte you.
Typically you'd add this as a constructor parameter:
public MyObj(Class<T> clazz) {
// This can throw all kinds of things, which you need to catch here or
// propagate.
T t = clazz.newInstance();
}
Judging by your comment above, you're looking for the following construct:
An interface with which you will interact with MyObj objects in code... you will be calling the test() method (standard style in Java is camelcase methods, capitalized classes/interfaces)
public interface IMyObj {
public void test();
}
You will want the abstract superclass... for the example that you've chosen, you don't NEED to specify any genericism, although you absolutely can if the actual implementation is more reliant on type safety... this class should implement the IMyObj interface:
public abstract class MyObj implements IMyObj {
String name;
public abstract String getName();
public void test() {
name = getName();
}
}
From here you would write your subclasses to MyObj...
public class MySubObj1 extends MyObj {
public String getName() { return "MySubObj1"; }
}
public class MySubObj2 extends MyObj {
public String getName() { return "MySubObj2"; }
}
Then you safely and correctly use the following snippet in another class:
IMyObj obj = new MySubObj1();
obj.test();
The key is that you use interfaces to hide the implementation, and use abstract classes to hold common code that subclasses will utilize in their implementations.
Hope this helps!

Categories

Resources