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()
{
}
}
Related
According to https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods
It is possible to explicitly invoke an interface base implementation with the following syntax.
base(IInterfaceType).Method();
But this doesn't seem to be implemented yet.
Is there a workaround (e.g reflection) to achieve this?
Example code to illustrate the problem
interface IA
{
void M()
{
Console.WriteLine("IA.M");
}
}
interface IB : IA
{
void IA.M()
{
Console.WriteLine("IB.M");
}
}
interface IC : IA
{
void IA.M()
{
Console.WriteLine("IC.M");
}
}
class D : IA, IB, IC
{
public void M()
{
// base(IB).M(); Is not yet supported apparently
((IB)this).M(); // Throws stack overflow
}
}
class Program
{
static void Main(string[] args)
{
D d = new D();
d.M();
}
}
The link in the question points to a version of the proposal copied from the proposal document in Github
The feature was cut in April 2019
Conclusion
Cut base() syntax for C# 8. We intend to bring this back in the next major release.
The design meeting doc explains that without runtime support (which wouldn't be available in time), the implementation would be workable at best for C# but not VB.NET.
If B.M is not present at run time, A.M() will be called. For base() and interfaces, this is not supported by the runtime, so the call will throw an exception instead. We'd like to add support for this in the runtime, but it is too expensive to make this release.
We have some workarounds, but they do not have the behavior we want, and are not the preferred codegen. Our implementation for C# is somewhat workable, although not exactly what we would like, but the VB implementation would be much more difficult. Moreover, the implementation for VB would require the interface implementation methods to be public API surface.
As for the infinite recursion, this
public void M()
{
((IB)this).M(); // Throws stack overflow
}
That's essentially
public void M()
{
M(); // Throws stack overflow
}
Default interface members are called the same way explicitly implemented interface methods are, through the interface. Besides, you're asking to call the method on this, not base.
There is a workaround.
I got it working, using GetFunctionPointer
Warning do not use this code
static class BaseInterfaceInvocationExtension
{
private static readonly string invalidExpressionMessage = "Invalid expression.";
public static void Base<TInterface>(this TInterface owner, Expression<Action<TInterface>> selector)
{
if (selector.Body is MethodCallExpression methodCallExpression)
{
MethodInfo methodInfo = methodCallExpression.Method;
string name = methodInfo.DeclaringType.FullName + "." + methodInfo.Name;
Type type = owner.GetType();
InterfaceMapping interfaceMapping = type.GetInterfaceMap(typeof(TInterface));
var map = interfaceMapping;
var interfaceMethod = map.InterfaceMethods.First(info =>
info.Name == name);
var functionPointer = interfaceMethod.MethodHandle.GetFunctionPointer();
var x = methodCallExpression.Arguments.Select(expression =>
{
if (expression is ConstantExpression constantExpression)
{
return constantExpression.Value;
}
var lambda = Expression.Lambda(Expression.Convert(expression, expression.Type));
return lambda.Compile().DynamicInvoke();
}).ToArray();
Type actionType = null;
if (x.Length == 0)
{
actionType = typeof(Action);
}else if (x.Length == 1)
{
actionType = typeof(Action<>);
}
else if (x.Length == 2)
{
actionType = typeof(Action<,>);
}
var genericType = actionType.MakeGenericType(methodInfo.GetParameters().Select(t => t.ParameterType).ToArray());
var instance = Activator.CreateInstance(genericType, owner, functionPointer);
instance.GetType().GetMethod("Invoke").Invoke(instance, x);
}
else
{
throw new Exception(invalidExpressionMessage);
}
}
}
class D : IA, IB, IC
{
public void M(int test)
{
this.Base<IB>(d => d.M(test));
}
}
class Program
{
static void Main(string[] args)
{
D d = new D();
d.M(12);
Console.ReadKey();
}
}
This is a workaround. It isn't ideal. Perhaps it will help someone.
class C : IB
{
public void IBM() => (this as IB).M();
}
class D : IA, IB, IC
{
private C _c = new C();
public void M()
{
_c.IBM();
}
}
Alternatively, this could work:
...
interface IB : IA
{
void IA.M()
{
IB_M();
}
void IB_M()
{
Console.WriteLine("IB.M");
}
}
...
class D : IA, IB, IC
{
public void M()
{
(this as IB).IB_M();
}
}
Not ideal either but less verbose.
I want to get the Type of the object from the reference of the IList
public interface A
{
}
public class B : A
{
//Some properties
}
public class C : A
{
//Some properties
}
List<B> b = new List<B>();
IList<A> a = new List<A>(b);
Type type = a.GetType();
if(type == typeof(IList<B>)){
//some code
}else if(type == typeof(IList<C>)){
//Some code
}
The type should be a List of B as the object of List of B is created.
IList<A>
Just try like this;
List<B> b = new List<B>()
{
new B {Sample = "Sample" }
};
IList<A> a = new List<A>(b);
var typeList = a.GroupBy(x => x.GetType()).Select(type => type.Key).ToList();
// Getting different types and grouping them
if (typeList.Count == 1)
{
if (typeList[0] == typeof(B))
{
//some code
}
else if (typeList[0] == typeof(C))
{
//Some code
}
}
else
{
//There are multiple different types in the list
}
You want to compare list elements which has implementation type and you can compare it by grouping items as Type.
Try this approach, but it only works with no empty list.
public static void Main()
{
IList<B> b = new List<B>(){ new B() };
IList<A> a = new List<A>(b);
if(a.All(x=>x is B))
Console.WriteLine("B");
else if(a.All(x=>x is C))
Console.WriteLine("C");
else
Console.WriteLine("A");
}
Here's some code to give the idea.
public class C<T> { }
public class X {
void M() {
var V = new { W = 1 };
var X = new C<V>(); // illegal
}
}
So V is a variable of an anonymous type and I would like to instantiate class C with V as its argument. This requires a type argument, which I cannot supply.
This questions is similar but the answer is not much help in my case: Why can't I instantiate a generic class inferring types from anonymous objects?
The question behind the question is that I'm trying to do what IEnumerable can do.
Should have made it clear: I would really prefer not to do this by manipulating object or Type because you lose the benefits of strong typing and Intellisense.
For anyone interested, the project that needs this is described here: http://www.andl.org/2016/07/andl-net-making-progress/.
You can use type inference if you have a factory method:
public class C<T>
{
public C(T t)
{
// ...
}
}
public static class Factory
{
public static C<T> Create<T>(T t)
{
return new C<T>(t);
}
}
public class Thing
{
void Foo()
{
var x = new { y = "z" };
//var thing = new C(x); - doesn't work, you need to specify the generic parameter
var thing = Factory.Create(x); // T is inferred here
}
}
You can't do that since V is instance of anonymous type, not a type name itself.
You can create this type dynamically (assuming parameterless constructor in C<>):
var X = typeof (C<>)
.MakeGenericType(V.GetType())
.GetConstructor(Type.EmptyTypes)
.Invoke(new object[0]);
You need a type, you can use pass object as a type.
Sample code:
public class C<T>
{
public T _t { get; set; }
public C(T t)
{
_t = t;
}
public void TestMethod()
{
Console.WriteLine(_t.ToString());
}
}
public class X
{
public void M()
{
var V = new { W = 1 };
var X = new C<object>(V); // everything is an object.
X.TestMethod();
}
}
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
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; }
}