Generic method with dynamic T - c#

I'm making a small example to check the type of parameter is valid or not.
class A
{
}
class B
{
}
class C
{
}
class D
{
public void SomeMethod<T>(T t) where T : class
{
if (t is A)
{
A a = t as A;
}
else if (t is B)
{
B b = t as B;
}
}
}
Then, I can call:
A a = new A();
SomeMethod<A>(a);
B b = new B();
SomeMethod<B>(b);
Now, I want to prevent to passing class C to SomeMethod. What I want to achieve:
C c = new C();
SomeMethod<C>(c); // error
To do that, I've tried:
public void SomeMethod<T>(T t) where T : A
{
// accept only class A
}
or
public void SomeMethod<T>(T t) where T : B
{
// accept only class B
}
My question is: how to declare SomeMethod with T can be A or B at the same time? Just like:
public void SomeMethod<T>(T t) where T : A, B
{
// accept class A and class B
}

As Lee has mentioned, this defeats the purpose of generics. To ahieve what you're describing just write overloads for each case
class A { }
class B { }
class C { }
class D
{
public void SomeMethod(A a)
{
//Do stuff with a
}
public void SomeMethod(B b)
{
//Do stuff with b
}
}
If you wanted to have a run-time error you could do something like this:
class A { }
class B { }
class C { }
class D
{
public void SomeMethod<T>(T t) where T : class
{
if (t is A)
{
A a = t as A;
}
else if (t is B)
{
B b = t as B;
}
else //if (t is C)
{
throw new ArgumentException();
}
}
}
Though this is a poor solution. The overload solution is still cleaner and will give a compile-time error.

It seems like really bad practice but I think you could do
class D
{
public void SomeMethod<T>(T t) where T : class
{
if (t is A)
A a = t as A;
else if (t is B)
B b = t as B;
else
throw new Exception("Wrong class type.");
}
}
This way you can use the method with only classes A and B, and it will throw an error for class C - and others.

Related

How to access members of an inherited object from a base

I am sorry for the unclear title, I wasn't really sure how to word it.
I have an interface; lets call it Iinterface;
public interface Iinterface
{
//Some members
}
I also have an abstract class that inherits from Iinterface; lets call this one Aabstract, and this one has a method called dosomething().
public abstract class Aabstract : Iinterface
{
public void dosomething()
{
}
}
I have a List<Iinterface> called listofIinterfaces in a part of my code in which each Iinterface may or may not be an Aabstract
How might I do something like the following (but working)
foreach (Iinterface a in listofIinterfaces)
{
if (a is Aabstract)
{
a.dosomething();
}
}
As suggested in the comments, you can use as to attempt to cast the appropriate type:
namespace Sample {
public interface IThing {
}
public class Type1 : IThing {
public void Foo() { }
}
public class Type2 : IThing {
public void Bar() { }
}
public class Program {
static void Main(string[] args) {
var list = new List<IThing> {
new Type1(),
new Type2()
};
foreach (var item in list) {
var t1 = item as Type1;
if (t1 != null) {
t1.Foo();
}
}
}
}
}
If you're using C# 7.0 you can also switch on type, the example is taken from here:
switch(shape)
{
case Circle c:
WriteLine($"circle with radius {c.Radius}");
break;
case Rectangle s when (s.Length == s.Height):
WriteLine($"{s.Length} x {s.Height} square");
break;
case Rectangle r:
WriteLine($"{r.Length} x {r.Height} rectangle");
break;
default:
WriteLine("<unknown shape>");
break;
case null:
throw new ArgumentNullException(nameof(shape));
}

Implementation of factory method in related class hierarchies

Please see the code:
class X
{
public string x;
}
class Y : X
{
public string y;
}
class A
{
string a;
public virtual X createX<T>()
where T : X, new()
{
return new T() { x = a };
}
}
class B : A
{
string b;
public override X createX<T>()
{
var x = base.createX<T>();
if (x is Y)
((Y)x).y = b; // Yak.
return y;
}
}
...
var c = new B();
var z = c.createX<Y>(); // Yak. I prefer to not needing to know the type Y
I dislike this code, trying to come up with the better way to refactor it. The general idea is quite simple, each class of the hierarchy has factory method to produce an instance of the counterpart class of mirror hierarchy. I get an instance of the root class or derivative class and need to return the instance of counterpart class or its derivative (as root counterpart class). Any ideas or design pattern I can implement instead?
This is what I have ended up with. All yacks removed. But it is a bit verbose.
class X
{
public string x;
}
class Y : X
{
public string y;
}
class A
{
string a;
protected void setX(X x)
{
x.x = a;
}
public virtual X createX()
{
var x = new X();
setX(x);
return x;
}
}
class B : A
{
string b;
protected void setY(Y y)
{
base.setX(y);
y.y = b;
}
public override X createX()
{
var y = new Y();
setY(y);
return y;
}
}
...
var c = new B();
var z = c.createX();
Could this be what you want ?
class BaseProduct
{
public string x;
}
class ChildProduct : BaseProduct
{
public string y;
}
class BaseFactory
{
string a;
public virtual BaseProduct buildProduct(BaseProduct product = null)
{
if (product == null)
product = new BaseProduct();
product.x = a;
return product;
}
}
class ChildFactory : BaseFactory
{
string b;
public override BaseProduct buildProduct(BaseProduct product = null)
{
if (product == null)
product = new ChildProduct();
//else if (!(product is ChildProduct))
// return null or throw exception
((ChildProduct)product).y = b;
return base.buildProduct(product); //build BaseProduct.x
}
}
...
var cFactory = new ChildFactory();
var cProduct = c.buildProduct(); //create a ChildProduct with x=a, y=b
buildProduct determine whether it has been requested to create a new
product of its own, or some derived-factory requesting it to build its
own part only
You should provide some safeguard mechanism of your own, like checking
whether the product is a derived class from ChildProduct in
ChildFactory.buildProduct. That'll avoid user from passing something like:
childFactory.buildProduct(new BaseProduct()); //yak

C# Override and New At Same Time

I'm looking for the best way to implement the following situation (.NET 3.5):
interface IGetThing<T>
{
T Get();
}
class BaseGetter<A> : IGetThing<A> where A : new()
{
public virtual A Get()
{
return new A();
}
}
class DerivedGetter<B, A> : Base, IGetThing<B> where B : A, new() where A : new()
{
public override A Get()
{
return Get(); //B version
}
public new virtual B Get()
{
return new B();
}
}
I've evaluated posts like This one, but I cannot see a solution that it would provide that is equivalent.
I've seen suggestions that I use explicit interface implementation to do something similar, but I don't see how that solves the inheritance issue:
If Get() was implemented explicitly in both places, it wouldn't solve the problem of: ((IGetThing<A>)new DerivedGetter<B, A>()).Get() calling the base method, instead of the desired derived method.
Attempting to implement both IGetThing and IGetThing in DerivedGetter causes a compilation exception. ('DerivedGetter' cannot implement both 'IGetThing' and 'IGetThing' because they may unify for some type parameter substitutions)
Also, attempting to re-implement BaseGetter's explicit implementation (IGetThing<A>.Get()) in DerivedGetter also provides a compilation exception (The obvious 'DerivedGetter.IGetThing<...>.Get()': containing type does not implement interface 'IGetThing')
The goal is to hide and override the base's Get() when using Derived.
Does anyone have any ideas?
EDIT: The overall solution would preferably be able to scale to multiple layers of derived classes.
As an aside, this only started giving me compilation issues when I changed from .NET 4 to .NET 3.5.
This new implementation takes your comments into account. I don't mind saying this - this is weird.
First thing - you have to do away with static generic constraints that the derived getter's generic parameters are related. You can still check this, but it's a run time.
interface IGetThing<T>
{
T Get();
}
class BaseGetter<A> : IGetThing<A> where A : new()
{
public BaseGetter()
{
var generics = this.GetType().GetGenericArguments();
for (var i = 0; i < generics.Length - 1; i++)
{
if (generics[i].BaseType != generics[i+1])
{
throw new ArgumentException(
string.Format("{0} doesn't inherit from {1}",
generics[i].FullName,
generics[i + 1].FullName));
}
}
getters = new Dictionary<Type, Func<object>>();
getters.Add(typeof(A), () => new A());
}
protected readonly IDictionary<Type, Func<object>> getters;
protected object Get(Type type)
{
var types = type.GetGenericArguments();
return getters[types[0]]();
}
public virtual A Get()
{
return (A) Get(this.GetType());
}
}
class DerivedGetter<B, A> : BaseGetter<A>, IGetThing<B>
where B : new() where A : new()
{
public DerivedGetter()
{
getters.Add(typeof(B), () => new B());
}
B IGetThing<B>.Get()
{
return (B) Get(this.GetType());
}
}
class Derived2Getter<C, B, A> : DerivedGetter<B, A>, IGetThing<C>
where C : new() where B : new() where A : new()
{
public Derived2Getter()
{
getters.Add(typeof(C), () => new C());
}
C IGetThing<C>.Get()
{
return (C) Get(this.GetType());
}
}
class Aa { }
class Bb : Aa { }
class Cc : Bb { }
class Dd { }
Use of methods (same as before!):
var a = new DerivedGetter();
Console.WriteLine(a.Get() is Bb);
var b = (IGetThing)a;
Console.WriteLine(b.Get() is Bb);
var c = new Derived2Getter<Cc, Bb, Aa>();
Console.WriteLine(c.Get() is Cc);
var d = (IGetThing<Bb>)c;
Console.WriteLine(d.Get() is Cc);
var e = (IGetThing<Aa>)c;
Console.WriteLine(e.Get() is Cc);
var f = new DerivedGetter<Dd, Aa>();
Output:
True
True
True
True
True
Unhandled Exception: System.ArgumentException:
ConsoleApplication16.Dd doesn't inherit from
ConsoleApplication16.Aa
Old implementation below.
I don't think you can do this with the (just) type system. You have to implement both interfaces, either through the base class, or the derived class.
With that in mind, I may consider approaching this problem with injecting in the behavior you want as a protected member to the base class.
Something like this:
interface IGetThing
{
T Get();
}
class BaseGetter<A> : IGetThing<A> where A : new()
{
protected IGetThing<A> Getter { get; set; }
public virtual A Get()
{
return Getter == null ? new A() : Getter.Get();
}
}
class DerivedGetter<B, A> : BaseGetter<A>, IGetThing<B> where B : A, new() where A : new()
{
public DerivedGetter()
{
Getter = this;
}
public override A Get()
{
return new B();
}
B IGetThing<B>.Get()
{
return (B) Get();
}
}
class Aa { }
class Bb : Aa { }
When ran,
var a = new DerivedGetter<Bb, Aa>();
Console.WriteLine(a.Get() is Bb);
var b = (IGetThing<Aa>)a;
Console.WriteLine(b.Get() is Bb);
outputs:
True
True
After hours of thinking, and a good night's sleep, I've come up with a viable solution that retains the original interface, and scales to multiple levels of inheritance without exploding too much.
interface IGetThing<T>
{
T Get();
}
class BaseGetter<A> : IGetThing<A>
where A : new()
{
public A Get()
{
A result;
GetInternal(out result);
return result;
}
protected virtual void GetInternal(out A target)
{
target = new A();
}
}
class DerivedGetter<B, A> : BaseGetter<A>, IGetThing<B>
where B : A, new()
where A : new()
{
public new B Get()
{
B result;
GetInternal(out result);
return result;
}
protected override void GetInternal(out A target)
{
target = Get();
}
protected virtual void GetInternal(out B target)
{
target = new B();
}
}
class Derived2Getter<C, B, A> : DerivedGetter<B, A>, IGetThing<C>
where C : B, new()
where B : A, new()
where A : new()
{
public new C Get()
{
C result;
GetInternal(out result);
return result;
}
protected override void GetInternal(out B target)
{
target = Get();
}
protected virtual void GetInternal(out C target)
{
target = new C();
}
}
When implemented an run through:
class Aa { }
class Bb : Aa { }
class Cc : Bb { }
class Program
{
static void Main(string[] args)
{
BaseGetter<Aa> getter = new DerivedGetter<Bb, Aa>();
Console.WriteLine("Type: " + getter.Get().GetType().Name);
getter = new Derived2Getter<Cc, Bb, Aa>();
Console.WriteLine("Type: " + getter.Get().GetType().Name);
}
}
The console output is
Type: Bb
Type: Cc

Get controls that implement an interface using Linq?

I have a number of controls that inherit from a generic base class and this class implements an interface IMyInterface.
So far I tried:
var results = from c in this.Controls.Cast<Control>()
where c.GetType().GetInterfaces().Contains(typeof(IMyInterface))
select c as IMyInterface;
However, the above doesn't return any results even though it should.
How can I use Linq to get a list of controls on a form that implement this interface?
If I understood you correctly, you could basically use:
var results = this.Controls.OfType<BaseGeneric>().ToList();
Given the following extension method:
public static class TypeExtensions
{
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
}
You want something like:
var result = from c in this.Controls.Cast<Control>()
where c.GetType().BaseTypesAndSelf().Any(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(BaseGeneric<>))
select c;
You might want to have your BaseGeneric<T> inherit from some even more abstract BaseGenericBase, or implement some non-generic IBaseGeneric interface, to make this sort of thing simpler.
class Program
{
static void Main(string[] args)
{
A test1 = new A();
B test2 = new B();
C test3 = new C();
List<object> test4 = new List<object>() { test1, test2, test3 };
List<object> test5 = test4.FindAll(x => x is A).ToList();
}
}
public class A
{
public A() { }
}
public class B
{
public B() {}
}
public class C : A
{
public C()
:base()
{
}
}

Generic method declaration

I have hierarchy of classes:
class A{}
class B: A {}
class C:B {}
is it possible to implement method in class A and it would be inherited by derived classes B and C and so on and that method should return value of class type?
A val = A.method(); (val is A)
B val = B.method(); (val is B)
C val = C.method(); (val is C)
And I don't want use of generics in call of this method, ie:
C val = C.method<C>();
Guys, excuse me, one elaboration, this method should be static.
I don't want to use generic in method istelf, because it forces to point type that method should return, whereas method should return type of its class.
class A
{
Method<T>()
{
T result;
return result;
}
}
If I have such method I can change return type:
D result = A.Method<D>();
but I wanted it to return value of type A;
No, that is not possible.
To call the method like that it would have to be static, and static methods are not inherited.
Using B.method() to call a static method in A is the same as using A.method(). The compiler just uses the type to determine where the method is, but it's impossible for the method to know if it was called using the A or B type.
Use an extension method:
class Program
{
static void Main(string[] args)
{
B x = new B();
x.Method();
}
}
public static class Ext
{
public static T Method<T>(this T obj)
where T : A,new()
{
return new T();
}
}
public class A
{
}
public class B : A
{
}
Or a variation thereof. Note that you must have some public member capable of creating an instance of the specified type. To expound, the compiler 'guesses' the value of the type parameter. The method is still generic, but generic syntax is nowhere to be seen when the method is called (usually).
Using some design patterns from C++ makes this easier:
class A
{
protected virtual A method_impl() { return new A(); }
public A method() { return method_impl(); }
}
class B : A
{
protected override A method_impl() { return new B(); }
public new B method() { return (B)method_impl(); }
}
class C : B
{
protected override A method_impl() { return new C(); }
public new C method() { return (C)method_impl(); }
}
Of course, this exact problem never arises in C++, which allows covariant return types for overrides.
Another way, using IoC pattern:
class A
{
protected virtual void method_impl(A a) { a.initialize(); }
public A method() { A result = new A(); method_impl(result); return result; }
}
class B : A
{
public new B method() { B result = new B(); method_impl(result); return result; }
}
class C : B
{
public new C method() { C result = new C(); method_impl(result); return result; }
}

Categories

Resources