I have the following problem.
class A
{
public bool Execute(int a);
}
class B
{
public bool Execute(bool a);
}
static class Consumer
{
public bool Validate(Delegate d);
}
I would like to to be able to Call the Consumer's Validate method from inside the "A" and "B" Classes with the execute method as an argument
Inside A or B :
public static main()
{
x = new A()
x1 = A.Execute(1);
y = new B()
y1 = B.Execute(true)
Consumer.Validate(x1)
Consumer.Validate(y1)
}
Of course this could work, but it would not do what I want it to. It would Execute and create a bool value X1 and not store it as a delegete to be executed at a certain point I Choose or to stre it as as internal object i a collection and then reExecute it.
I hope I got it over to you so you can understand my intentions.
But how to forward it with the argumets.
This is simplified explanation of the problem, but still the same.
Is it possible to pack the arguments with the methods delegate in the consumer, and then just execute them.
You could use lambda
public bool Execute(int a)
{
Consumer.Validate(() => this.Execute(a));
}
The lambda () => this.Execute(a) will store the value of a inside itself and provide to Validate simple you-should-know-nothing interface.
And better change the signature of Validate to:
public bool Validate(Func<bool> paramLessPredicate);
I think you need both delegate and value as arguments in the Consumer.Validate function:
public bool Validate<T>(Funct<T,bool> validator, T value)
{
bool validatorResult = validator(value);
// Do whatever..
return someBool;
}
And in A:
int value = 10;
bool result = Consumer.Validate(Execute, value);
Related
I have a generic class of two types, "MyClass<T,U>". Based on a parameter to the class constructor, I'd like to be able to set a "Func<T,U>" local variable in a class instance that can be called to efficiently invoke a static method with input type T and output type U. The work done on the input variable depends on the input type. Can this be done?
Here's some code I've been playing with...
namespace ConsoleApp {
public class MyClass<T, U> {
// First constructor. Pass in the worker function to use.
public MyClass(Func<T, U> doWork) {
_doWork = doWork;
}
// Second constructor. Pass in a variable indicating the worker function to use.
public MyClass(int workType) {
if (workType == 1) _doWork = Workers.Method1;
else if (workType == 2) _doWork = Workers.Method2;
else throw new Exception();
}
// User-callable method to do the work.
public U DoWork(T value) => _doWork(value);
// Private instance variable with the worker delegate.
private Func<T, U> _doWork;
}
public static class Workers {
public static ushort Method1(uint value) => (ushort)(value >> 2);
public static uint Method1(ulong value) => (uint)(value >> 1);
public static ushort Method2(uint value) => (ushort)(value >> 3);
public static uint Method2(ulong value) => (uint)(value >> 4);
}
public class Program {
public static void Main(string[] args) {
var mc1 = new MyClass<uint, ushort>(Workers.Method1);
var mc2 = new MyClass<ulong, uint>(Workers.Method1);
var mc3 = new MyClass<uint, ushort>(Workers.Method2);
var mc4 = new MyClass<ulong, uint>(Workers.Method2);
var mc5 = new MyClass<uint, ushort>(1);
var mc6 = new MyClass<ulong, uint>(1);
var mc7 = new MyClass<uint, ushort>(2);
var mc8 = new MyClass<ulong, uint>(2);
}
}
}
The first constructor works just fine: the compiler is able to infer the correct overload of the static worker method to pass as a parameter, which gets stored in the instance variable _doWork, and can be (reasonably) efficiently called.
The second constructor won't compile, however, The problem is the assignments to _doWork which fail because "No overload for 'Method_' matches delegate 'Func<T,U>'". I sort of get it but sort of don't. It seems the compiler knows what T and U are at compile time, is "substituting" them into the class definition when compiling, and, so, ought to be able to infer which worker method to use. Anyone know why not?
Anyway, for reasons not worth going into, I'd really like to make the second constructor work. The obvious thing to try is to "cast" Method1 or Method2 to Func<T,U>, but delegates aren't objects and can't be cast. I've found a couple of pretty ugly ways to do it (that are also horribly inefficient), but I can't help but feeling there is something easier I'm missing. Any other ideas?
EDIT: It sounds like I'm abusing generics. What I have are about 100 different combinations of possible T, U, Worker values (there's actually a fourth dimension, but ignore that), each that behave somewhat differently. I'm trying to avoid having to create a separate class for each combination. So this isn't "generics" in the sense of being able to plug in any types T and U. What, if any, alternatives are there?
Have you considered using something like a factory pattern and resolving the service in a manner similar to this example
void Main()
{
var serviceCollection = new Microsoft.Extensions.DependencyInjection.ServiceCollection();
serviceCollection.AddSingleton<IMessageDeliveryProcessor, InAppNotificationMessageProcessor>();
serviceCollection.AddSingleton<IMessageDeliveryProcessor, MessageProcessor>();
serviceCollection.AddSingleton<IMessageProcessorFactory, MessageProcessorFactory>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var factoryItem = serviceProvider.GetService<IMessageProcessorFactory>();
var service = factoryItem.Resolve(DeliveryType.Email);
service.ProcessAsync("", "", "");
}
public enum DeliveryType
{
Email,
InApp,
}
public class MessageProcessorFactory : IMessageProcessorFactory
{
private readonly IServiceProvider _serviceProvider;
public MessageProcessorFactory(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider;
public IMessageDeliveryProcessor? Resolve(DeliveryType deliveryType)
=> _serviceProvider
.GetServices<IMessageDeliveryProcessor>()
.SingleOrDefault(processor => processor.DeliveryType.Equals(deliveryType));
}
public interface IMessageProcessorFactory
{
IMessageDeliveryProcessor? Resolve(DeliveryType deliveryType);
}
public interface IMessageDeliveryProcessor
{
DeliveryType DeliveryType { get; }
Task ProcessAsync(string applicationId, string eventType, string messageBody);
}
public class InAppNotificationMessageProcessor : IMessageDeliveryProcessor
{
public DeliveryType DeliveryType => DeliveryType.InApp;
public Task ProcessAsync(string applicationId, string eventType, string messageBody)
{
Console.Write("InAppNotificationMessageProcessor");
return Task.CompletedTask;
}
}
public class EmailNotificationMessageProcessor : IMessageDeliveryProcessor
{
public DeliveryType DeliveryType => DeliveryType.Email;
public Task ProcessAsync(string applicationId, string eventType, string messageBody)
{
Console.Write("MessageProcessor");
return Task.CompletedTask;
}
}
This doesnt address your code and your issue exactly, but based on what I see of your issue, this could help you in the direction of travel.
In your second constructor, you are attempting to assign something not directly compatible. What you're assigning is a method group, of which nothing in the method group can match a T or a U using the compiler's type inference rules.
One thing you can do is instead of trying to assign the delegates directly in your second destructor, you can instead assign a dispatcher method that will resolve this at runtime.
Your constructor could be changed to
public MyClass(int workType)
{
if (workType == 1) _doWork = Method1Dispatcher;
else if (workType == 2) _doWork = Method2Dispatcher;
else throw new Exception();
}
where you have dispatcher methods such as
public U Method1Dispatcher(T value)
{
return value switch
{
uint x => (U)(object)Workers.Method1(x),
ulong x => (U)(object)Workers.Method1(x),
_ => throw new NotSupportedException()
};
}
public U Method2Dispatcher(T value)
{
return value switch
{
uint x => (U)(object)Workers.Method2(x),
ulong x => (U)(object)Workers.Method2(x),
_ => throw new NotSupportedException()
};
}
These methods use a double cast to get around the compile-time checks that prevent you from "equating", for instance, a uint and a T. Casting to object removes that constraint, and casts to another type, at runtime, could either succeed or fail. That's not typesafe, but if implemented carefully like the above, you at least encapsulate known (to us not the compiler) safe casts.
To test that this works, you can modify your Main method to prove it
var mc5 = new MyClass<uint, ushort>(1);
var mc5Result = mc5.DoWork(5);
Console.WriteLine($"Got result {mc5Result} of type {mc5Result.GetType().Name}");
var mc6 = new MyClass<ulong, uint>(1);
var mc6Result = mc6.DoWork(6);
Console.WriteLine($"Got result {mc6Result} of type {mc6Result.GetType().Name}");
var mc7 = new MyClass<uint, ushort>(2);
var mc7Result = mc7.DoWork(7);
Console.WriteLine($"Got result {mc7Result} of type {mc7Result.GetType().Name}");
var mc8 = new MyClass<ulong, uint>(2);
var mc8Result = mc8.DoWork(8);
Console.WriteLine($"Got result {mc6Result} of type {mc8Result.GetType().Name}");
Now, while this works, it's probably not the best solution because you say there are hundreds of combinations. Perhaps you can replace the switch with a reflection based way of obtaining the correct method, and then invoking it.
I am consuming some external library that have one method which except parameter as Func type.
class LibClass
{
public void libMethod(Func<int, int, int> add)
{
add(5, 5);
}
}
In my Console app i am consuming like
class Program
{
public static int MyMethod(int a, int b) // want to pass third parameter
{
return 0;
}
static void Main(string[] args)
{
LibClass obj = new LibClass();
obj.libMethod(Program.MyMethod);
Console.Read();
}
}
I want to pass some additional parameter to MyMethod(), but i am not able to pass it. so how can change library method signature?
or how i can pass additional parameter to MyMethod()?
You would have to recompile the library from source in order to change its methods, but I think this might be an XY Problem. You shouldn't need to change the signature to pass another parameter to your method. Example:
int DoSomeMath(int a, int b, int x)
{
return (a + b) * x;
}
If you wanted to have libMethod call DoSomeMath with more parameters, you can just wrap it in a lambda and add your own:
void Main()
{
LibClass obj = new LibClass();
obj.libMethod((a, b) => DoSomeMath(a, b, 42));
Console.Read();
}
The lambda will receive a and b from libMethod, pass those along with 42 to DoSomeMath, and return the return value of DoSomeMath back to libMethod.
I have an abstract parent class which child classes that inherit from it. I have another class that contains many List<> types of the different child classes. I then have a method in another class that takes a parameter of List<ParentType> and just calls the methods that are declared abstract.
I'm having a problem using List<T>.Cast<T2> on the lists of the child classes. I'm getting the error:
System.Linq.Enumerable.Cast(System.Collections.IEnumerable)' is a 'method', which is not valid in the given context
Does anybody know how to fix this error? Or do I have to reconstruct a list of type List<ParentType> and recast each item individually?
What I'm trying to do:
public abstract class P {
public int num;
public abstract double addSections();
}
public class A : P {
public int num2;
public A(int r, int n) {
num = r;
num2 = n;
}
public double addSections() { return (double)num + (double)num2; }
}
public class B : P {
public double g;
public B(int r, double k) {
num = r;
g = k;
}
public double addSections() { return (double)num + g; }
}
public class MyClass {
public MyClass() {
List<A> listA;
List<B> listB;
//...
helper(listA.Cast<P>()); //doesn't work
helper(listB.Cast<P>().ToList()); //doesn't work either
}
public void helper(List<P> list) {
//...
}
}
In lieu of actually seeing your code so we can fix it, how about changing the method instead:
public void DoSomething<T>(IEnumerable<T> items) where T : ParentType
{
...
}
Or if you're using C# 4 and .NET 4, this should be fine, as IEnumerable<T> is covariant in T in .NET 4.
public void DoSomething(IEnumerable<ParentType> items)
{
...
}
Do you really need the method to accept a List<ParentType>? After all, if you're going to call:
var parentList = childList.Cast<ParentType>().ToList();
and pass that into the method, then you've got two entirely separate lists by that point anyway.
By the way, another effect of the covariant of IEnumerable<T> is that in .NET 4 you can avoid the Cast call and just call:
var parentList = childList.ToList<ParentType>();
EDIT: Now that you've posted your code, it's simply a matter of not calling the Cast method as a method:
// This...
helper(listB.Cast<P>.ToList())
// should be this:
helper(listB.Cast<P>().ToList())
Now that you've added code, I see two potential problems:
You need to add parentheses when calling Cast e.g.
listA.Cast<P>()
Cast is not some special operator, it's an extension method like anything else.
Are those calls to helper actually at the class level, and not inside another method? That would be a problem too.
I'm trying to figure out a way to automatically cast something to an Action or Func and the best I can come up with is something like this:
[TestFixture]
public class ExecutionTest
{
public void BadMethod()
{
throw new Exception("Something bad happened");
}
[Test]
public void TestBadMethod()
{
// Want this, but it won't work!!
// BadMethod.Execute().IgnoreExceptions();
// Ick
((Action)BadMethod).Exec().IgnoreExceptions();
// Still ick
((Action)BadMethod).IgnoreExceptions();
// Do not want
ExtensionMethods.Exec(BadMethod).IgnoreExceptions();
// Better but still meh
this.Exec(BadMethod).IgnoreExceptions();
}
}
public static class ExtensionMethods
{
public static Action Exec(this Action action)
{ return action; }
public static Action Exec(this object obj, Action action)
{ return action; }
public static void IgnoreExceptions(this Action action)
{
try { action(); }
catch {}
}
}
There has to a better/easier way to do this, any thoughts?
In C#, when you use the method name without parenthesis, it's called a method group and it has no representation other than at compile time. A method group can represent more than one method (because of overloads and overrides), therefore to implicitly identify which method is needed, a target delegate type must be provided.
In your case, you are wondering why the extension method parameter type won't trigger the resolution of the function. Simply put, extension are evaluated after the type is known, that is, the this parameter can't be used as an implicit conversion target.
Example of why it would break:
class Test
{
void M (void) // Fits Action delegate
{
}
int M (int) // Fits Func<int,int> delegate
{
return 5;
}
void Test()
{
M.Exec(); // UHOH!!! Which Exec to resolve to ???
}
}
public static class Extensions
{
public static void Exec(this Action action) { }
public static void Exec(this Func<int, int> func) { }
}
As you can see, there is a conflict, but as a matter of fact, the conflict never happens because C# won't even try to find a matching extension with a method group.
Note how this won't work either:
class A
{
public static implicit operator int (A a)
{
return 5;
}
void F()
{
A a = new A();
a.Blah(); // Error! It won't implicitly try C.Blah()
}
}
public static class C
{
public static void Blah (int i)
{
}
}
C# won't match A to C.Blah(int) because it would require an implicit conversion.
As Coincoin says, it's not gonna work well in C# because of the overzealous love for method overloading. The only workaround I've seen people use is to create Action and Func methods:
public Action Action(Action f) { return f; }
public Action<A> Action<A>(Action<A> f) { return f; }
...
public Func<A,B,C,D,E> Func(Func<A,B,C,D,E> f) { return f; }
You could even call them all "F" to get some sort of short syntax:
F(BadMethod).NoExceptions();
You might decide to not define these methods in your class, and put them in a Funcs utility or something. Alias it with F and it doesn't end up too bad:
F.F(BadMethod).NoException();
But overall it still sucks :(.
F# lets you do this kind of thing very naturally by providing a much better type inference system.
How would you do specialization in C#?
I'll pose a problem. You have a template type, you have no idea what it is. But you do know if it's derived from XYZ you want to call .alternativeFunc(). A great way is to call a specialized function or class and have normalCall return .normalFunc() while have the other specialization on any derived type of XYZ to call .alternativeFunc(). How would this be done in C#?
In C#, the closest to specialization is to use a more-specific overload; however, this is brittle, and doesn't cover every possible usage. For example:
void Foo<T>(T value) {Console.WriteLine("General method");}
void Foo(Bar value) {Console.WriteLine("Specialized method");}
Here, if the compiler knows the types at compile, it will pick the most specific:
Bar bar = new Bar();
Foo(bar); // uses the specialized method
However....
void Test<TSomething>(TSomething value) {
Foo(value);
}
will use Foo<T> even for TSomething=Bar, as this is burned in at compile-time.
One other approach is to use type-testing within a generic method - however, this is usually a poor idea, and isn't recommended.
Basically, C# just doesn't want you to work with specializations, except for polymorphism:
class SomeBase { public virtual void Foo() {...}}
class Bar : SomeBase { public override void Foo() {...}}
Here Bar.Foo will always resolve to the correct override.
Assuming you're talking about template specialization as it can be done with C++ templates - a feature like this isn't really available in C#. This is because C# generics aren't processed during the compilation and are more a feature of the runtime.
However, you can achieve similar effect using C# 3.0 extension methods. Here is an example that shows how to add extension method only for MyClass<int> type, which is just like template specialization. Note however, that you can't use this to hide default implementation of the method, because C# compiler always prefers standard methods to extension methods:
class MyClass<T> {
public int Foo { get { return 10; } }
}
static class MyClassSpecialization {
public static int Bar(this MyClass<int> cls) {
return cls.Foo + 20;
}
}
Now you can write this:
var cls = new MyClass<int>();
cls.Bar();
If you want to have a default case for the method that would be used when no specialization is provided, than I believe writing one generic Bar extension method should do the trick:
public static int Bar<T>(this MyClass<T> cls) {
return cls.Foo + 42;
}
I was searching for a pattern to simulate template specialization, too. There are some approaches which may work in some circumstances. However what about the case
static void Add<T>(T value1, T value2)
{
//add the 2 numeric values
}
It would be possible to choose the action using statements e.g. if (typeof(T) == typeof(int)). But there is a better way to simulate real template specialization with the overhead of a single virtual function call:
public interface IMath<T>
{
T Add(T value1, T value2);
}
public class Math<T> : IMath<T>
{
public static readonly IMath<T> P = Math.P as IMath<T> ?? new Math<T>();
//default implementation
T IMath<T>.Add(T value1, T value2)
{
throw new NotSupportedException();
}
}
class Math : IMath<int>, IMath<double>
{
public static Math P = new Math();
//specialized for int
int IMath<int>.Add(int value1, int value2)
{
return value1 + value2;
}
//specialized for double
double IMath<double>.Add(double value1, double value2)
{
return value1 + value2;
}
}
Now we can write, without having to know the type in advance:
static T Add<T>(T value1, T value2)
{
return Math<T>.P.Add(value1, value2);
}
private static void Main(string[] args)
{
var result1 = Add(1, 2);
var result2 = Add(1.5, 2.5);
return;
}
If the specialization should not only be called for the implemented types, but also derived types, one could use an In parameter for the interface. However, in this case the return types of the methods cannot be of the generic type T any more.
By adding an intermediate class and a dictionary, specialization is possible.
To specialize on T, we create an generic interface, having a method called (e.g.) Apply. For the specific classes that interface is implemented, defining the method Apply specific for that class. This intermediate class is called the traits class.
That traits class can be specified as a parameter in the call of the generic method, which then (of course) always takes the right implementation.
Instead of specifying it manually, the traits class can also be stored in a global IDictionary<System.Type, object>. It can then be looked up and voila, you have real specialization there.
If convenient you can expose it in an extension method.
class MyClass<T>
{
public string Foo() { return "MyClass"; }
}
interface BaseTraits<T>
{
string Apply(T cls);
}
class IntTraits : BaseTraits<MyClass<int>>
{
public string Apply(MyClass<int> cls)
{
return cls.Foo() + " i";
}
}
class DoubleTraits : BaseTraits<MyClass<double>>
{
public string Apply(MyClass<double> cls)
{
return cls.Foo() + " d";
}
}
// Somewhere in a (static) class:
public static IDictionary<Type, object> register;
register = new Dictionary<Type, object>();
register[typeof(MyClass<int>)] = new IntTraits();
register[typeof(MyClass<double>)] = new DoubleTraits();
public static string Bar<T>(this T obj)
{
BaseTraits<T> traits = register[typeof(T)] as BaseTraits<T>;
return traits.Apply(obj);
}
var cls1 = new MyClass<int>();
var cls2 = new MyClass<double>();
string id = cls1.Bar();
string dd = cls2.Bar();
See this link to my recent blog and the follow ups for an extensive description and samples.
I think there is a way to achieve it with .NET 4+ using dynamic resolution:
static class Converter<T>
{
public static string Convert(T data)
{
return Convert((dynamic)data);
}
private static string Convert(Int16 data) => $"Int16 {data}";
private static string Convert(UInt16 data) => $"UInt16 {data}";
private static string Convert(Int32 data) => $"Int32 {data}";
private static string Convert(UInt32 data) => $"UInt32 {data}";
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Converter<Int16>.Convert(-1));
Console.WriteLine(Converter<UInt16>.Convert(1));
Console.WriteLine(Converter<Int32>.Convert(-1));
Console.WriteLine(Converter<UInt32>.Convert(1));
}
}
Output:
Int16 -1
UInt16 1
Int32 -1
UInt32 1
Which shows that a different implementation is called for different types.
Some of the proposed answers are using runtime type info: inherently slower than compile-time bound method calls.
Compiler does not enforce specialization as well as it does in C++.
I would recommend looking at PostSharp for a way to inject code after the usual compiler is done to achieve an effect similar to C++.
A simpler, shorter and more readable version of what #LionAM proposed (about half of the code size), shown for lerp since this was my actual use case:
public interface ILerp<T> {
T Lerp( T a, T b, float t );
}
public class Lerp : ILerp<float>, ILerp<double> {
private static readonly Lerp instance = new();
public static T Lerp<T>( T a, T b, float t )
=> ( instance as ILerp<T> ?? throw new NotSupportedException() ).Lerp( a, b, t );
float ILerp<float>.Lerp( float a, float b, float t ) => Mathf.Lerp( a, b, t );
double ILerp<double>.Lerp( double a, double b, float t ) => Mathd.Lerp( a, b, t );
}
You can then just e.g.
Lerp.Lerp(a, b, t);
in any generic context, or provide the method as a grouped Lerp.lerp method reference matching T(T,T,float) signature.
If ClassCastException is good enough for you, you can of course just use
=> ( (ILerp<T>) instance ).Lerp( a, b, t );
to make the code even shorter/simpler.
If you just want to test if a type is derrived from XYZ, then you can use:
theunknownobject.GetType().IsAssignableFrom(typeof(XYZ));
If so, you can cast "theunknownobject" to XYZ and invoke alternativeFunc() like this:
XYZ xyzObject = (XYZ)theunknownobject;
xyzObject.alternativeFunc();
Hope this helps.