are the two methods in the class "Confused" below the same?
class MyClass
{
public override string ToString()
{
return "I am confused now";
}
}
class Confused
{
public MyClass GetMyClass()
{
return new MyClass();
}
public T GetMyClass<T>() where T : MyClass, new()
{
return System.Activator.CreateInstance<T>();
}
}
class Program
{
static void Main()
{
Confused c = new Confused();
System.Console.WriteLine(c.GetMyClass());
System.Console.WriteLine(c.GetMyClass<MyClass>());
}
}
They produce different IL, but is there any reason to write the generic version other than the 'straight up' version other than to confuse the heck out of collegues :)
If you write the generic version, you can instantiate and return derived classes:
where T : MyClass
Also, with the generic version you don't need the activation code:
return new T();
This is because you have specified:
where T : new()
The generic constraint enforcing a public parameterless constructor.
Sure there's a difference. Let's say you have a second class deriving from MyClass:
class MyClass2 : MyClass { }
Then you can do
MyClass2 myClass2 = confused.GetMyClass<MyClass2>();
You can't do that with the other function.
MyClass could be a base class (or an interface IMyClass). The generic version with the constraint says you want this function to work for any class derived from (or implementing) a common base or interface and to return the result as that derived class, not as the base.
class MyClass { }
class MySpecializedClass : MyClass { }
// etc.
There is a very big difference:
The non generic version can only return instances of type MyClass, whereas the generic version can return instances of type MyClass and all classes derived from MyClass!
No. They are not the same. The first will only ever construct a MyClass object, and the second will construct any object that is a MyClass or a descendent of MyClass, based on the type parameter.
They would give the same result ONLY if you called .GetMyClass<MyClass>(). However, I presume the extra method has been created to allow for creation of other classes? If not, then they're the same, so one's redundant (and I'd get rid of the generic version as has overhead inside the assembly).
Are they being used differently?
They are not the same. The generic allows inherited classes to be built as well like this:
class MyClass
{
public override string ToString()
{
return "I am confused now";
}
}
class InheritedClass : MyClass
{
}
class Confused
{
public MyClass GetMyClass()
{
return new MyClass();
}
public T GetMyClass<T>() where T : MyClass, new()
{
return System.Activator.CreateInstance<T>();
}
}
class Program
{
static void Main()
{
Confused c = new Confused();
System.Console.WriteLine(c.GetMyClass());
System.Console.WriteLine(c.GetMyClass<MyClass>());
System.Console.WriteLine(c.GetMyClass<InheritedClass>());
}
}
I'm not quite sure, but Generics are a runtime feature in .NET. Therefore, the non-generic method isn't equivalent to the generic one, even though it is used equivalently. As they're public, this can't be optimized away.
Related
This might be a silly question and I don't really need this for anything but I was just curious...
The best way to describe it is using a example so here it is:
using System;
namespace GenericExample
{
public interface IFoo { }
public interface IFoo2 { }
public class Foo1: IFoo , IFoo2 { }
public class Foo2 : IFoo, IFoo2 { }
public class MyGeneric<T> where T : IFoo , IFoo2, new() { }
internal class Program
{
public static void Main(string[] args)
{
MyGeneric<Foo1> obj1 = new MyGeneric<Foo1>();
MyMethod(obj1);//I can treat obj1 as MyGeneric<T> in MyMethod
MyGeneric<Foo2> obj2 = new MyGeneric<Foo2>();
//But can I use is as MyGeneric<T> in this method???
//MyGeneric<?> obj3 = null;
//obj3 = (MyGeneric<?>)obj1;
//obj3 = (MyGeneric<?>)obj2;
Console.ReadLine();
}
public static void MyMethod<T>(MyGeneric<T> arg) where T : IFoo, IFoo2, new()
{
}
}
}
I don't think it is possible to treat obj1 as MyGeneric< T> in Main
but at the same time it feels strange since I can pass it as a MyGeneric< T> argument
You cannot cast it to MyGeneric<T> in Main because in the scope of Main there is no such type as T. Actually it's not really clear what you mean by
to treat obj1 as MyGeneric< T> in Main
When passing obj1 to MyMethod you don't "treat it as MyGeneric<T>". It is the compiler which infers the type of T for you. It knows that T is Foo1 here and translates your call
MyMethod(obj1);
to
MyMethod<Foo1>(obj1);
So the type of the parameter arg inside of MyMethod will at runtime also be MyObject<Foo1>, not an unspecified MyObject<T>.
There is no common base-type for MyGeneric and MyGeneric, so I assume the answer is no. In contrast to Java generics in C# are strongly typed types and not just placeholders, so they donĀ“t have anything in common - except a name. However actually they are different types, think of them as just MyGeneric<T1> being a type Foo and MyGeneric<T2> being Bar.
A way around this is to define a non-generic version of your generic class:
public class Foo1 { }
public class MyNonGeneric { }
public class MyGeneric<T> : MyNonGeneric where T : new() { }
I'm trying to code something, and I always return the object itself so I can keep chaining. Like this
object.SetThis().SetThat().SetThisThirdThing().setThisFourthThing();
I return this in all my methods so I can keep doing this. But one of my methods is something I made in my base class, which of course then returns the base class.
So instead of public MyClass SetThat() it returns public SuperClass SetThat(). And because it returns SuperClass and not MyClass I can't call SetThisThirdThing() because the base class doesn't know about it.
So how do I cast it so I can keep the chain? What is the syntax? I tried
object.SetThis().(MyClass)SetThat().SetThisThirdThing().setThisFourthThing();
Or is there a way to make a superClass method return the subclass when called from the subclass without having to override it in all the subclasses?
This is one of the things that all the subclasses have in common, so it would be really nice if I would be able to circumvent this somehow without having to override it in all my subclasses.
is there a way to make a superClass method return the subclass when called from the subclass without having to override it in all the subclasses?
Can you make the superclass generic?
public class SuperClass<T> where T: SuperClass<T>
{
public T SetThis()
{
....
return (T)this;
}
}
public class SubClass : SuperClass<SubClass>
{
}
Note that it's not 100% guaranteed since you could also do this:
public class EvilSubClass : SuperClass<SubClass>
{
}
which fits the generic contraints, but now the return type of SetThis() is SubClass and not EvilSubClass
var obj = ((MyType)myObject.SetThis()).SetThat();
P.S You should avoid doing that, since it can become quite confusing to read.
To cast a (sub)expression, you need to put the class name in front (and use parentheses).
((MyClass)obj.SetThis().SetThat()).SetThisThirdThing().setThisFourthThing();
(note that object is a reserved word, so you can't use it as a variable name)
An alternative is to use the as keyword:
(obj.SetThis().setThat() as MyClass).SetThisThirdThing().setThisFourthThing();
Note that this will behave differently if setThat() doesn't return a MyClass;
the first version will throw an InvalidCastException, the second version a NullReferenceException because as returns null if the cast is not possible.
Try like this:
((MyClass)object.SetThis().SetThat()).SetThisThirdThing()
Just use parenthesis:
(MyClass)(object.SetThis().SetThat()).SetThisThirdThing().setThisFourthThing();
I don't know why the object is there, but you can safely remove it.
(MyClass)(SetThis().SetThat()).SetThisThirdThing().setThisFourthThing();
Without modifying your classes, you can also write an extension method As like this
public static T As<T>(this MyBaseClass obj) where T : MyBaseClass
{
return (T)obj;
}
--
Usage would be similar to this
new MyChildClass().SetBase().As<MyChildClass>().SetThis();
Why not do it like this? A simple Cast method to help you cast it back to the correct type...
class Program
{
static void Main(string[] args)
{
var obj = new MyClass();
//obj.SetThis().SetThat().SetThisThirdThing().setThisFourthThing(); // Compile error
obj.SetThis().SetThat().Cast<MyClass>().SetThisThirdThing().setThisFourthThing();
}
}
class SuperClass
{
public SuperClass SetThat()
{
return this;
}
public T Cast<T>() where T : SuperClass
{
return (T)this;
}
}
class MyClass : SuperClass
{
public MyClass SetThis()
{
return this;
}
public MyClass SetThisThirdThing()
{
return this;
}
public MyClass setThisFourthThing()
{
return this;
}
}
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.
I have a class library which contain some base classes and others that are derived from them. In this class library, I'm taking advantage of polymorphism to do what I want it to do. Now in a consuming application, I want to change the behavior of some code based on the runtime type of the child classes. So assume the following:
public class Base { }
public class Child1 : Base { }
public class Child2 : Base { }
Now in the consuming application I want do something as follows (note that all of the following classes are in the consuming application and cannot be referenced in the class library):
public interface IMyInterface1 { }
public interface IMyInterface2 { }
public static class Extensions
{
public static void DoSomething(this Base myObj, Object dependency)
{
}
public static void DoSomething(this Child1 myObj, Object dependency)
{
IMyInterface1 myInterface = dependency as IMyInterface1;
if (myInterface != null)
{
//Do some Child1 specific logic here
}
}
public static void DoSomething(this Child2 myObj, Object dependency)
{
IMyInterface2 myInterface = dependency as IMyInterface2;
if (myInterface != null)
{
//Do some Child2 specific logic here
}
}
}
UPDATE:
This does not work. It always calls the extension method of the base class. Is there some other way that will allow me to do this and avoid having to explicitly check for the runtime type? The reasons is because more classes that are derived from the Base could be added and corresponding extension methods could come from some other external assembly.
Thanks in advance.
As #SLaks has already stated you cannot call the method as an extension method (even with a dynamic type) ... you can however call the static method with a dynamic type
So, although this will fail
Base base1 = new Child1();
(base1 as dynamic).DoSomething();
This will work
Base base1 = new Child1();
Extensions.DoSomething(base1 as dynamic);
No, that won't work.
Extension methods are statically dispatched, using the same mechanism as overload resolution.
If you have a variable of compile-time type Base, the compiler will always call the base extension method, regardless of the runtime type.
Instead, you can make the base extension method check the runtime type and call the appropriate other extension method.
I was looking for the same thing just now.
You could add one more method to your extension class like this:
public static void DoSomething(this Base myObj, Object dependency)
{
if(myObj.IsSubclassOf(Base))
{
// A derived class, call appropriate extension method.
DoSomething(myObj as dynamic, dependency);
}
else
{
// The object is Base class so handle it.
}
}
You don't need the if/else check if the base class is abstract (or never used in the wild):
public static void DoSomething(this Base myObj, Object dependency)
{
DoSomething(myObj as dynamic, dependency);
}
[Edit] Actually this won't work in your case as you don't implement support for all derived objects (so could still get infinite recursion). I guess you could pass something to check for recursion but the given answer is the simplest. I'll leave this here as it might spark more ideas.
Below is the minimal example showing how to mimic polymorphism with extension methods.
void Main()
{
var elements = new Base[]{
new Base(){ Name = "Base instance"},
new D1(){ Name = "D1 instance"},
new D2(){ Name = "D2 instance"},
new D3(){ Name = "D3 instance"}
};
foreach(Base x in elements){
x.Process();
}
}
public class Base{
public string Name;
}
public class D1 : Base {}
public class D2 : Base {}
public class D3 : Base {}
public static class Exts{
public static void Process(this Base obj){
if(obj.GetType() == typeof(Base)) Process<Base>(obj); //prevent infinite recursion for Base instances
else Process((dynamic) obj);
}
private static void Process<T>(this T obj) where T: Base
{
Console.WriteLine("Base/Default: {0}", obj.Name);
}
public static void Process(this D1 obj){
Console.WriteLine("D1: {0}", obj.Name);
}
public static void Process(this D2 obj){
Console.WriteLine("D2: {0}", obj.Name);
}
}
Outputs:
Base/Default: Base instance
D1: D1 instance
D2: D2 instance
Base/Default: D3 instance
If you can not use the keyword "dynamic" (older version of .NET), you can use reflection to achieve the same thing.
In place of :
Base base1 = new Child1();
Extensions.DoSomething(base1 as dynamic);
you can write :
Base base1 = new Child1();
MethodInfo method = typeof(Extensions).GetMethod("DoSomething", new System.Type[] { base1.GetType() });
if (method) {
method.Invoke(new object[] { base1 });
}
I have something like this:
abstract class BaseClass<T>
{
protected BaseClass(){}
}
class Class1 : BaseClass<Class1>
{
public static Class1 Instance = new Class1();
private Class1(){}
}
class Class2 : BaseClass<Class2>
{
public static Class2 Instance = new Class2();
private Class2(){}
}
...
public BaseClass<T> Method<T>(int z) where T: BaseClass<T>
{
switch(z)
{
case 1:
return Class1.Instance;
case 2:
return Class2.Instance;
}
}
That is very important that those classes cannot be instantiated since their construstors are private so we cannot do like
public BaseClass<T> Method<T>(int z) where T: BaseClass<T>, new()
How can I use abstract class as return type ?? I just can not work this out. Would appreciate for any assisstance here.
It sounds to me like you can't really have the method be generic. For instance, what would happen if I called:
BaseClass<Class1> foo = Method<Class1>(2);
You need a single point of truth - either the type argument, or the normal argument. You can make it the method argument by having a non-generic base class (either by making the existing base class non-generic, or introducing a non-generic base class to that). Change the return type of Method to this non-generic base class.
abstract class BaseClass<T>
{
public abstract T Instance { get; }
protected BaseClass(){}
}
maybe? You can't inherit static stuff I believe...
On a closer look... I don't think what you are trying to do is even possible... what are you trying to do anyways?
A type constraint is a type constraint. You are trying to change the type constraint in the method kind of. which obviously doesn't work, and shouldn't work. I think you need to think of a different way of attacking your problem. Whatever it is...
Take a look at the factory pattern. Your factory can have a method on it to get the instance. The first time it's called, it creates the instance. On subsequent calls, it can return the already-created instance.