I've been dealing a lot lately with abstract classes that use generics. This is all good and fine because I get a lot of utility out of these classes but now it's making for some rather ugly code down the line. For example:
abstract class ClassBase<T>
{
T Property { get; set; }
}
class MyClass : ClassBase<string>
{
OtherClass PropertyDetail { get; set; }
}
This implementation isn't all that crazy, except when I want to reference the abstract class from a helper class and then I have to make a list of generics just to make reference to the implemented class, like this below.
class Helper
{
void HelpMe<C, T>(object Value)
where C : ClassBase<T>, new()
{
DoWork();
}
}
This is just a tame example, because I have some method calls where the list of where clauses end up being 5 or 6 lines long to handle all of the generic data. What I'd really like to do is
class Helper
{
void HelpMe<C>(object Value)
where C : ClassBase, new()
{
DoWork();
}
}
but it obviously won't compile. I want to reference ClassBase without having to pass it a whole array of generic classes to get the function to work, but I don't want to reference the higher level classes because there are a dozen of those. Am I the victim of my own cleverness or is there an avenue that I haven't considered yet?
I suppose that your HelpMe method would be used for initializing the concrete ClassBase<T> type (a guess based on the constraints). To keep the code fully generic (if you need both T and C somewhere in the method), you probably need to keep both of the type parameters.
However, you could add a non-generic base class and then write something like this:
abstract class ClassBase {
object UntypedProperty { get; set; }
}
abstract class ClassBase<T> : ClassBase {
T Property { get; set; }
public override object UntypedProperty {
get { return Property; }
set { Property = (T)value; }
}
}
Then you could be to write the helper method like this:
void HelpMe<C>(object Value) where C : ClassBase, new() {
var n = new C();
c.UntypedProperty = Value;
}
Depending on your specific scenario, something along these lines might work and make the code a little bit simpler. However, you need to modify the base class to make this possible.
Generics do have a tendency to propogate through the code, and they're seldomly used as "mixin" classes for that reason.
Thomas mentioned the one possibility of introducing an equivalent non-generic API. I would prefer revisiting the design and making these base classes non-generic if possible while maintaining full type safety. Whether or not this is actually possible is determined by your requirements.
There is one other possibility short of a re-design (or API duplication): dynamic. If you're willing to lose IntelliSense in your helper methods (and are willing to pay a very, very small runtime performance penalty), you can use dynamic in your helper method:
class Helper
{
void HelpMe<C>(object Value)
// where C : ClassBase<T>, new() // no longer needed, but should be documented
{
dynamic cObj = Activator.CreateInstance<C>(); // instead of "new C()"
cObj.PropertyDetail = ...;
cObj.Property = ...;
...
}
}
without having to pass it a whole array of generic classes to get the function to work
A small change might ease these calls. Move repeatedly specified types to the generic declaration of the class.
//before
Helper x = new Helper();
x.HelpMe<MyClass, string>(x);
x.HelpMe<MyClass, string>(y);
//after
Helper x = new Helper<string>();
x.HelpMe<MyClass>(x);
x.HelpMe<MyClass>(y);
//the change
class Helper<T>
{
void HelpMe<C>(object Value)
where C : ClassBase<T>, new()
{
DoWork();
}
}
Related
The following code shows what I would like to do; that is, I would like to constrain anObject, so that it can be used as a parameter to various methods with use IInterfaceOne or IInterfaceTwo, where neither inherits from the other.
public interface IInterfaceOne { }
public interface IInterfaceTwo { }
public class Implementation : IInterfaceOne, IInterfaceTwo
{
}
public interface IInterfaceOneAndTwo : IInterfaceOne, IInterfaceTwo { }
public class UsingImplementation
{
IInterfaceOneAndTwo anObject = (IInterfaceOneAndTwo)(new Implementation()); //fails because Implementation doesnt acctually implement IInterfaceOneAndTwo
}
This example fails however as IInterfaceOneAndTwo is an interface in its own right, and Implementation does not implement it.
I know if I used generics I could constrain them, but I am wondering, if there is a way to do this without generics?
Is there a way to say anObject shall implement IInterfaceOne and IInterfaceTwo, without using IInterfaceOneAndTwo?
Not the way you have it currently. Only generic constraints have that ability.
You could rewrite it to use generics:
public class UsingImplementation<T>
where T : IInterface1, IInterface2, new()
{
T anObject = new T();
void SomeMethod() {
anObject.MethodFromInterface1();
}
}
You can also have generic methods, not only generic classes
public void DoSomething<T>(T value)
where T : IInterface1, IInterface2
{
value.DoInterface1Things();
value.DoInterface2Things();
}
Or
public void DoSomething<T>()
where T : IInterface1, IInterface2, new()
{
T anObject = new T();
}
You can't do that in C# without generics but there is an alternative workaround to solve the problem without generics that was not mentioned here and might fit for you. This style is often used together with the IoC principle. You could inject the same object twice. Let me change your sample quite a bit...
public interface IInterfaceOne { void Hello(); }
public interface IInterfaceTwo { void World(); }
public class Implementation : IInterfaceOne, IInterfaceTwo
{
public void Hello() { };
public void World() { };
}
public class UsingImplementation
{
private readonly IInterfaceOne one;
private readonly IInterfaceTwo two;
public UsingImplentation(IInterfaceOne one, IInterfaceTwo two)
{
this.one = one;
this.two = two;
}
// do the stuff you want to do with an IInterfaceOne using field one
public DoSomeThingWithOne() { one.Hello(); }
// do the stuff you want to do with an IInterfaceTwo using field two
public DoSomeThingWithTwo() { two.World(); }
}
Then you could wire up the things this way:
var oneAndTwo = new Implementation();
var a = new UsingImplementation(oneAndTwo, oneAndTwo);
// operates on the first param (which is the same as the second)
a.DoSomeThingWithOne();
// operates on the second param (which is the same as the first)
a.DoSomeThingWithTwo();
Have a look for IoC principle (Inversion of Control) and Dependency Injection and you'll find more solutions similiar to this one.
This way you don't need to create an extra Interface combining InterfaceOne and InterfaceTwo, two.
"Incoming" generic class parameters and generic method parameters can combine types, but there is no facility for variables or fields to represent "composite" types. Further, in order to pass an object to a parameter of a generic type which combines multiple constraints, the object must be cast to a type which in fact implements all of those constraints. This can be difficult.
For example, suppose class Foo and Bar both implement Intf1 and Intf2. One wishes to write a function AddToList<T>(thing as T) where T:Intf1,Intf2. Such a function will perfectly happily accept objects of type Foo or Bar. Suppose, however, one wishes to use such a function to add all objects to the same list (which might be a mix of Foo, Bar, and any number of other types that also happen to implement Intf1 and Intf2) and then later pass those objects to a function whose parameter is likewise constrained to implement both Intf1 and Intf2. One could cast to Foo any object which happened to be a Foo, and cast to Bar any object which happened to be a Bar, but if other types are written which also handle Intf1 and Intf2, it would be difficult to deal with them.
It is possible to solve the problem, somewhat awkwardly, without using Reflection or other such tricks. Define an interface IActUpon<Base1, Base2> with a method ActUpon<thingType>ActUpon(thingType thing) where thingType: Base1, Base2. Implementations of such a method will be able to pass parameter thing to other methods requiring generic method parameter constrained to Base1 and Base2. The biggest difficulties with such an approach are that one must write separate code for each possible number of constraints, and that in many places where one would have used a lambda expression one will instead have to write an implementation of IActUpon....
If this is desirable then there has to be a logical connection between IInterfaceOne and IInterfaceTwo and the implementing class should implement the combined interface:
class Implementation : IInterfaceOneAndTwo { ... }
If this is not possible, because it's not (all) your code then you may have to rethink the UsingImplementation. It simply doesn't fit the available surface.
Sounds like silly idea but I was wondering if it's possible somehow.
Is it possible to change the base class of a derived class at runtime? Of course, there are lot of ifs and buts and the the question of why would someone do it and its a bad design probably and all that.
Keeping all those aside (even though they might be perfectly valid), let's say, just for kicks or to show your nerdiness, is it possible in C# or any language for that matter?
So something like:
public class baseOriginal {
public string justAProperty;
}
public class baseSwapped {
public int sillyNumber;
}
public class derivedClass : baseOriginal {
public bool iAmDumb;
}
void Main() {
baseOriginal derived = new derivedClass ();
Console.WriteLine(derived.justAProperty);
baseSwapped derivedSwapped = (??);
Console.WriteLine(derivedSwapped.sillyNumber);
}
It isn't possible in C#. Probably what you want is more of a prototype-based solution commonly found in dynamic languages like JavaScript where you can "extend" the functionality of the object by adding to how it's defined.
But to accomplish what your code hints at doing, you can have the swappable classes inherit from a common ancestor class. That way you can assign instances of each to their decendents.
public class baseClassAncestor{
}
public class baseOriginal:baseClassAncestor {
public string justAProperty;
}
public class baseSwapped:baseClassAncestor {
public int sillyNumber;
}
public class derivedClass : baseOriginal {
public bool iAmDumb;
}
You can do one time base class swap by loading different assemblies that implement base class BEFORE using derived class. But this approach will not make your exact code working as you will not be able to compile that - but moving access to methods of different base classes to separate functions could be made working.
You add UnionBase class that contains all possible methods/properties from all base classes so you can compile your Main code against the assembly with this class. Than at run time you load assembly that has contains your particular base class.
Usual warning: You need to have very good reasons and understanding for going this route. I.e. existing external code is a reason to consider such approach.
"Don't do it at home, performed on a closed course by trained professional".
One more possible workaround could be implemented using some AOP solution that is based on compile-time weaving, i.e. PostSharp, which is able to seamlessly inject new methods and interfaces to existing types as well as modify (intercept) existing ones.
There is actually a good reason where you may want to swap the base class. Let say you want to modify the base class but you don't wan't to perturb the current code base as it is shared among other teams. Let say there are 10+ derived class that inherits from base. You could create 10+ custom derived classes to override the base class but that is a lot of work. Here is what you do. The key to the problem is to create an interface and a base proxy class.
class Program
{
static void Main(string[] args)
{
IActionable action = new Derived<Base1>();
action.open();
action = new Derived<Base2>();
action.open();
}
}
// Proxybase is a fake base class. ProxyBase will point to a real base1 or
// base2
public class Derived<T>:ProxyBase,IActionable
{
public Derived():base(typeof(T))
// the open function is not overriden in this case allowing
// the base implementation to be used
}
// this looks like the real base class but it is a fake
// The proxy simply points to the implementation of base1 or base2 instead
public abstract class ProxyBase: IActionable
{
IActionable obj;
public ProxyBase(Type type,params object[] args)
{
obj = (IActionable)Activator.CreateInstance(type,args);
}
public virtual void open()
{
obj.open();
}
}
// notice base1 and base2 are NOT abstract in this case
// consider this the original implementation of the base class
public class Base1: IActionable
{
public virtual void open()
{
Console.WriteLine("base1 open");
}
}
// here base2 acquired the functionality of base1 and hides base1's open
function
// consider this implementation the new one to replace the original one
public class Base2: Base1, IActionable
{
public new virtual void open()
{
Console.WriteLine("base2 open");
}
}
public interface IActionable
{
void open();
}
The result would be as follows
base1 open
base2 open
UPDATE:
Although this answer works, the reality is that inheritance introduces coupling which makes this exercise difficult at best. Also, in a practical scenario, your requirements may lead you to want to derive from multiple base class which is not possible in c#. If you want to interchange the base class you are best to use the bridge design pattern (which in fact avoids inheritance altogether thus avoiding the coupling).
The closest thing I can think of is the following:
http://msdn.microsoft.com/en-us/library/dd264736.aspx
static void Main(string[] args)
{
ExampleClass ec = new ExampleClass();
// The following line causes a compiler error if exampleMethod1 has only
// one parameter.
//ec.exampleMethod1(10, 4);
dynamic dynamic_ec = new ExampleClass();
// The following line is not identified as an error by the
// compiler, but it causes a run-time exception.
dynamic_ec.exampleMethod1(10, 4);
// The following calls also do not cause compiler errors, whether
// appropriate methods exist or not.
dynamic_ec.someMethod("some argument", 7, null);
dynamic_ec.nonexistentMethod();
}
class ExampleClass
{
public ExampleClass() { }
public ExampleClass(int v) { }
public void exampleMethod1(int i) { }
public void exampleMethod2(string str) { }
}
I have no idea if the dynamic language runtime can do what you want it to do.
Closest you could get would be to
derive from both types by defining at
least one as an interface, then
casting derived from one to the other.
I would have to agree, based on the example this suggestion would satisfy what he wants to do, it also is a better design then what he actually wants to do.
Closest you could get would be to derive from both types by defining at least one as an interface, then casting derived from one to the other.
I have a "Product" base class, some other classes "ProductBookDetail","ProductDVDDetail" inherit from this class. I use a ProductService class to make operation on these classes. But, I have to do some check depending of the type (ISBN for Book, languages for DVD). I'd like to know the best way to cast "productDetail" value, I receive in SaveOrupdate. I tried GetType() and cast with (ProductBookDetail)productDetail but that's not work.
Thanks,
var productDetail = new ProductDetailBook() { .... };
var service = IoC.Resolve<IProductServiceGeneric<ProductDetailBook>>();
service.SaveOrUpdate(productDetail);
var productDetail = new ProductDetailDVD() { .... };
var service = IoC.Resolve<IProductServiceGeneric<ProductDetailDVD>>();
service.SaveOrUpdate(productDetail);
public class ProductServiceGeneric<T> : IProductServiceGeneric<T>
{
private readonly ISession _session;
private readonly IProductRepoGeneric<T> _repo;
public ProductServiceGeneric()
{
_session = UnitOfWork.CurrentSession;
_repo = IoC.Resolve<IProductRepoGeneric<T>>();
}
public void SaveOrUpdate(T productDetail)
{
using (ITransaction tx = _session.BeginTransaction())
{
//here i'd like ot know the type and access properties depending of the class
_repo.SaveOrUpdate(productDetail);
tx.Commit();
}
}
}
I don't mean to be critical, but that pattern just feels bad to me.
I've heard others say that if you're taking a type in a generic method, then you're most likely doing something wrong.
I would refactor your code by declaring a base class method to help with the SaveOrUpdate method, then have the derived classes override that method. Now when you call the base class method in the generic method, you will get the derived classes implmentation
Nooooo
If you have non generic properties (as specified in common interface contract) then you should have a common function declared in the interface that is called by SaveOrUpdate to handle this
Each instance of the common interface (ProductDetailBook, productDetail etc) will define this function differently as required by "//here i'd like ot know the type and access properties depending of the class"
You are pulling class specific code and putting it into a common function, this is the start of spaghetti code
This is one of the many reasons NOT to have generic services
If you need to know about the fields or properties of the type in order to "save or update", you could use reflection. That way, the class would remain truly generic.
If within your SaveOrUpdate method you mean to write an ever-expanding switch equivalent to:
if (it's type A) { deal with type A }
else if (it's type B) { deal with type B }
... and so on
Then you're doing it "wrong". That class is not really generic in its type parameter. It only works with the specific set of types you specified. I say "wrong" in quotes because it might be better than the available alternatives in some situations, but it's undesirable. If you have a fall-back for all other types, so it always works, then it might be an okay way to have special cases for certain types.
However, you can do such a test, or casting. With an unconstrained type parameter, T, you need to cast it to object first:
var eitherStringOrNull = (string)((object)somethingOfTypeT);
With the as keyword you shouldn't need that extra cast to object.
var eitherStringOrNull = somethingOfTypeT as string;
if (eitherStringOrNull != null)
{
.. it was a string, so we can use it as such
}
But even better, if there is a common base class, ProductDetail, for all kinds of product detail class, then use that as a constraint on T:
public class ProductServiceGeneric<T> : IProductServiceGeneric<T>
where T : ProductDetail
I think it's good practise when doing that to use a more meaningful name for the type parameter, such as TProductDetail.
If you do this, then the compiler should let you "cast down" to something derived from ProductDetail, without having to cast to object first.
If I understand your question you are trying to determine what derived class you have from a function that returns a base class. You need to use the IS operator
you can see how to use the operator below.
class Base
{
}
class AB : Base
{
}
class AC : Base { }
class Program
{
static Base GetObject()
{
return null;
}
static void Main(string[] args)
{
Base B = GetObject();
if (B is AB)
{
AB DevClass =(AB) B;
}
}
}
}
Within generic methods, you have to cast with as keyword to do casts like this. There are good reasons why but its a long story...
If you do a lot with generics, read Bill Wagners "More Effective C#" for alternative ways to dealing with this more cleanly.
public void SaveOrUpdate(T productDetail)
{
using (ITransaction tx = _session.BeginTransaction())
{
ProductDetailBook bookDetail = productDetail as ProductDetailBook;
if (bookDetail != null)
_repo.SaveOrUpdate(bookDetail);
tx.Commit();
}
}
Maybe you should refactor your code as follows:
abstract class Product
{
public abstract bool CheckProduct();
}
class ProductBookDetail : Product
{
public override bool CheckProduct()
{
//Here we can check ProductBookDetail
}
}
class ProductDetailDVD : Product
{
public override bool CheckProduct()
{
//Here we can check ProductDetailDVD
}
}
public class ProductServiceGeneric<T> : IProductServiceGeneric<T> where T : ProductDetail
{
public void SaveOrUpdate(T product)
{
if (!product.CheckProduct())
{
//product checking failes. Add necessary logic here
}
}
}
This code is much more appropriate for OOP. It much simpler, it more extensible and less error prone.
P.S. Don't forget about S.O.L.I.D.
I would look up Strategy pattern and maybe use that in conjunction with your generic repository. Then you can define your strategy in some interface for your entities, which forces them to implement some method like CheckConstraints. In your generic repository you then call CheckConstraints before executing SaveOrUpdate.
Use:
if(productDetail is ProductDetailBook)
{
...
...
}
and similarly for others.
class test <T> where T : class
{
public void Write<T>()
{
Console.Write(typeof(T).FullName);
}
}
In the above class, it is possible to pass in a string for the class (test<string> Test = new test<string>) and then int for the method? If so, what is the output? If not, what problems does this cause? I haven't actually tried this, despite using generics (in my own classes) and generic collections, frequently.
The way I write/see generic classes is as follows:
class <T> where T : class
{
public T Write()
{
Console.Write(T.ToString());
}
}
As it was originally written no you cannot. In order to use different types at different points in the class, you must have multiple generic parameters. It is possible to define a different one at the method level and get your sample to work
class Test<T> where T : class {
public void Write<U>(U arg1) {
Console.WriteLine(arg1.ToString());
}
}
Usage
var t = new Test<string>();
t.Write(42);
As Scott pointed out you can use the same named parameter. Although doing so will cause a warning and generally speaking confuse people. It is much cleaner to have distinct names for all generic parameters currently in scope.
You'll be wanting to declare a type variable in the method separately to the class -
class Test<T> where T : class {
public void Method<U>(U val) {
Console.WriteLine(typeof(U).FullName);
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?
I can do
public class MyGenericClass : DL
//but i cannot do
public class MyGenericClass <T> : T
How would i do the second? if i cannot do that, how can i do something like
public class MyGenericClass <T>
{
T obj;
//have all MyGenericClass.XYZ call obj.XYZ
}
This is not possible, because depending on what type T is, the public interface of MyGenericClass would change.
If you have lots of different classes that all expose the same interface, you could declare MyGenericClass to expose that interface, and in the implementation of all of the functions delegate the calls to obj
The specific question, why can't you do this:
public class MyGenericClass<T> : T
And you can do this:
public class MyGenericClass<T>
{
T obj;
}
The reason is that the CLR likes to be able to compile a single version of the code for MyGenericClass that will work for any reference type specified for T.
It can do this for the second case, because it can quietly replace T with object and insert appropriate casts, roughly equivalent to:
public class MyGenericClass
{
object obj;
}
But for the inheritance version, that trick doesn't work.
Also, many useful facilities would be impossible to describe through interface constraints. When you inherit from a type, you can do a lot more than just call methods on it - you can override them as well. Consider this hypothetical example:
class MyBase
{
public virtual void MyVirtual() { }
}
class MyGenericDerived<T> : T
{
public override void MyVirtual()
{
Console.WriteLine("Overridden!");
}
}
MyBase obj = new MyGenericDerived<MyBase>();
obj.MyVirtual();
What I want to do there is something like a "mix-in", where MyGenericDerived supplies definitions for virtual functions in whatever base it is applied to. But how does the compiler know that T will have a method called MyVirtual that can be overridden? I'd need to put a constraint on T. How would I express that through interfaces? It's impossible. Using interfaces to describe constraints isn't an adequate solution once you allow inheritance from type parameters. So that's another reason why it doesn't exist in the language today.
You could do something like
public interface IXyzable { void xyz(); }
public class MyGenericClass<T> : IXyzable where T : IXyzable {
T obj;
public void xyz() {
obj.xyz();
}
}
Edit: Now I understand the question
You'll need all your possible T's to implement some interface so that you know that obj.XYZ() makes sense, then you can do
public interface Ixyz
{
void XYZ();
}
public class MyGenericClass<T> : Ixyz where T:Ixyz, new()
{
T obj;
public MyGenericClass()
{
obj = new T();
}
public void XYZ()
{
obj.XYZ();
}
}
I've made MyGenericClass implement Ixyz too since it obviously does expose the right method, but maybe that's best left out since it allows
var x = new MyGenericClass<MyGenericClass<SomeClass>>();
which is unlikely to ever be a good idea.
This is pretty much duck-typing, but you could use reflection.
When you create the generic class with a reference to the obj, use reflection to try and find a method with the right signature. As long as you store a reference to the method, performance won't be too bad.
class BaseGeneric<T>
{
private T obj;
private MethodInfo mi;
private const string MethodNameOfInterest = "Xyz";
public BaseGeneric(T theObject)
{
this.obj = theObject;
Type t = obj.GetType();
mi = t.GetMethod(MethodNameOfInterest);
}
public void Xyz()
{
mi.Invoke(obj, null);
}
}
Of course, you would need to add a lot more for error checking and such, but that is the gist of what you could do. Also, don't forget to add the System.Reflection namespace to your using clause.
The .NET type system won't allow type declarations of the form you're attempting. One reason why this is disallowed should be intuitive: how would MyGenericClass<T> act when T is a sealed class (e.g. System.String)?
If you absolutely need this functionality (and you know that the type T you'll be using isn't sealed), you can generate proxies at runtime using the classes in the Reflection.Emit namespace. It may also be possible to achieve this effect using AOP tools like PostSharp.
What about this:
class BaseClass<T>
{
public T property { get; set; }
}
class GenericClass<T> : BaseClass<T>
{
}
class Program
{
static void Main(string[] args)
{
GenericClass<int> l = new GenericClass<int>();
l.property = 10;
}
}
This achieves what you want to do?