Generic method declaration - c#

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; }
}

Related

C# 8 base interface's default method invocation workaround

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.

Inheritance - Invoke child methods instead of parent

It is going to be hard to explain why Im doing the things im about to show you, but they have a reason so stay with me here. (suggestions are welcome).
I have a Functor which invokes a method on its input.
!Please note! the functor is actually an extension method so there must be a typing inference.
Also, I have an abstract class with 2 childs and an interface which demands a method signature.
The example code looks like this:
public sealed class AbstractionTester
{
internal static void Run()
{
// The functor here accepts A type but in my original code its just a generic type.
// I wanted to keep it simple for this example only
Func<A, bool> func = a =>
{
a.CallMe(); //Displays "Error"
return true;
};
B obj = new B();
func(obj);
}
}
internal interface ICallMe<T>
where T : MyEntity
{
T CallMe();
}
//Just a class which holds data I would like to store about every object I have, for example: CreateDate
internal abstract class MyEntity
{ }
internal abstract class A : MyEntity, ICallMe<A>
{
//some other fields i would like to store..
// This method here must never be invoked
public A CallMe()
{
//throw new Exception();
Console.WriteLine("Error");
return this;
}
}
internal class B : A, ICallMe<B>
{
public new B CallMe()
{
Console.WriteLine("B");
return this;
}
}
internal class C : A, ICallMe<C>
{
public new C CallMe()
{
Console.WriteLine("C");
return this;
}
}
Everytime I call Run() the result is the Error is yeilded to the screen.
What can I do to enforce that this functor I have won't execute the method in the parent class.
Functor will never receive an instance of A anyway, because A is abstract (I mean pure A, not child of A)
Additional info:
I must explicity write the return types of CallMe in class B and C. I CANNOT change them to type A.
I need to keep the type of A (or something similar) in the functor because I need to infer the type for some code continuation.
It is really weird implementation. Why dont you use Visitor pattern?
Then you can do:
static void Main(string[] args)
{
Element a = new A();
Element b = new B();
Element c = new C();
ICallMe callMe = new CallMe();
a.accept(callMe);
b.accept(callMe);
c.accept(callMe);
}
Implementation below:
public interface ICallMe
{
void Visit(A a);
void Visit(B b);
void Visit(C c);
}
public class CallMe : ICallMe
{
public void Visit(A c)
{
Console.WriteLine("A");
}
public void Visit(B b)
{
Console.WriteLine("B");
}
public void Visit(C a)
{
Console.WriteLine("C");
}
}
interface Element
{
void accept(ICallMe visitor);
}
public class A : Element
{
public void accept(ICallMe visitor)
{
visitor.Visit(this);
}
}
public class B : Element
{
public void accept(ICallMe visitor)
{
visitor.Visit(this);
}
}
public class C : Element
{
public void accept(ICallMe visitor)
{
visitor.Visit(this);
}
}
Here is a solution that works without defining public A CallMe() as virtual. This has the benefit that child classes can define their CallMe() as new so they can return B or C. But it requires that you can make the classes public instead of internal (or you will get an error).
Use dynamic dispatch to call the actual runtime type instead of the type declared in the interface:
Func<A, bool> func = a => {
var runtimeType = (dynamic)a;
runtimeType.CallMe();
return true;
};
.net Fiddle
There is a specific language feature for this; interface reimplementation.
Reimplement explicitly the interface and make the generic functor take an ICallable<T>:
internal class B : A, ICallMe<B>
{
B ICallable<B>.CallMe()
{
Console.WriteLine("B");
return this;
}
}
internal class C : A, ICallMe<C>
{
B ICallable<C>.CallMe()
{
Console.WriteLine("B");
return this;
}
}
And your functor should be:
Func<T, bool> func = a => ...
And T should be constrained (at method or class level) to ICallable<T>.
UPDATE: If the functor is really an extension code, I'm not sure what the issue is:
public static bool MyEnxtensionMethod<T>(T argument)
where T: ICallable<T>
{
argument.CallMe();
return true;
}
Why do you need to keep A anywhere?
The best way to ensure that A's CallMe method is never invoked is for it to not exist.
internal abstract class MyEntity
{ }
internal abstract class A : MyEntity
{ }
Now it can never be invoked as you required.
Now make the interface covariant:
internal interface ICallMe<out T>
where T : MyEntity
{
T CallMe();
}
Then change Func<A, bool> to Func<ICallMe<A>, bool>
public sealed class AbstractionTester
{
internal static void Run()
{
// The functor here accepts A type but in my original code its just a generic type.
// I wanted to keep it simple for this example only
Func<ICallMe<A>, bool> func = a =>
{
a.CallMe(); //Displays "B"
return true;
};
B obj = new B();
func(obj);
}
}

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()
{
}
}

How does Lazy<T> get around needing new() constraint?

Example 1 (does not compile):
void Main()
{
var c = new C<D>();
c.M.F();
}
class C<T>
{
T _m = null;
public T M { get {
if(_m == null) _m = new T();
return _m;
} }
}
class D
{
public void F() { Console.WriteLine ("i was created"); }
}
Result:
Cannot create an instance of the variable type 'T' because it does not have the new() constraint
Example 2 (works):
void Main()
{
var c = new C<D>();
c.M.F();
}
class C<T>
{
Lazy<T> _m = new Lazy<T>();
public T M { get { return _m.Value; } }
}
class D
{
public void F() { Console.WriteLine ("i was created"); }
}
Result:
i was created
If you delve into the source code, you'll see that Lazy<T> ultimately uses Activator:
return new Lazy<T>.Boxed((T)Activator.CreateInstance(typeof(T)));
This is just a shortcut for using reflection. Since it's not instantiating the type via the actual generic type argument (new T()) but rather invoking the constructor through reflection, no where T : new() constraint is needed.

C#: Generic types that have a constructor?

I have the following C# test code:
class MyItem
{
MyItem( int a ) {}
}
class MyContainer< T >
where T : MyItem, new()
{
public void CreateItem()
{
T oItem = new T( 10 );
}
}
Visual Studio can't compile it, the error is at line where 'new' is used:
'T': cannot provide arguments when creating an instance of a variable type
Is it possible in C# to create an object of generic type with non-parameterless constructor? It's no problem to do such thing in C++ templates, so i'm very curious why i can't do same thing in C#. Maybe some additional 'where' is required or syntax is different?
C#, and VB.Net for that matter, do not support the notion of constraining a generic to have a constructor with specific parameters. It only supports constraining to have an empty constructor.
One work around is to have the caller pass in a factory lambda to create the value. For instance
public void CreateItem(Func<int,T> del) {
T oItem = del(10);
}
Call site
CreateItem(x => new SomeClass(x));
It can be done with reflection:
public void CreateItem()
{
int constructorparm1 = 10;
T oItem = Activator.CreateInstance(typeof(T), constructorparm1) as T;
}
But there is no generic constraint to ensure that T implements the desired constructor, so I wouldn't advise doing this unless you are careful to declare that constructor in every type that implements the interface.
There's no such generic constraint, so it's not possible directly (this is a CLR limitation). If you want this, you have to provide a factory class (which has a parameterless constructor), and pass it as a second generic type parameter.
IMO, the best approach here is an initialize method, i.e.
interface ISomeInterface {
void Init(int i);
}
class Foo : ISomeInterface {
void ISomeInterface.Init(int i) { /* ... */ }
}
static class Program {
static T Create<T>(int i) where T : class, ISomeInterface, new() {
T t = new T();
t.Init(i);
return t;
}
static void Main() {
Foo foo = Create<Foo>(123);
}
}
However, you can do what you want with Expression (but without compile-time support):
using System;
using System.Linq.Expressions;
class Foo {
public Foo(int i) { /* ... */ }
}
static class Program {
static T Create<T>(int i) {
return CtorCache<T>.Create(i);
}
static class CtorCache<T> {
static Func<int, T> ctor;
public static T Create(int i) {
if (ctor == null) ctor = CreateCtor();
return ctor(i);
}
static Func<int, T> CreateCtor() {
var param = Expression.Parameter(typeof(int), "i");
var ci = typeof(T).GetConstructor(new[] {typeof(int)});
if(ci == null) throw new InvalidOperationException("No such ctor");
var body = Expression.New(ci, param);
return Expression.Lambda<Func<int, T>>(body, param).Compile();
}
}
static void Main() {
Foo foo = Create<Foo>(123);
}
}
Note that this caches and reuses the delegate for performance.
One pattern I use is to have the constrained class implement an interface which defines an Init method with the appropriate signature:
interface IMyItem
{
void Init(int a);
}
class MyItem : IMyItem
{
MyItem() {}
void Init(int a) { }
}
class MyContainer< T >
where T : MyItem, IMyItem, new()
{
public void CreateItem()
{
T oItem = new T();
oItem.Init( 10 );
}
}

Categories

Resources