c# method as parameter where method contains ref paramater [duplicate] - c#

This question already has answers here:
Delegate for an Action< ref T1, T2>
(2 answers)
Closed 7 years ago.
I have got the following method
public static void Method1(ref List<int> list)
{//code to update list}
Is it possible to create a method that takes this method as a parameter similar to (but instead of Action< List> it uses Action< ref List>)
public static void Method2(Action<List<int>> otherMethod)
{var newList = new List<int>(); otherMethod(newList)}
My main problem is that my method uses reference while Action> does not take references. Is this possible?

Yes, but you can't use Action<>/Func<> for it, you have to build the delegate "manually":
// Your method
public static void Method1(ref List<int> list)
{
}
// The delegate
public delegate void Method1Delegate(ref List<int> list);
// A method that accepts the delegate and uses it
public static void Method2(Method1Delegate del)
{
List<int> list = null;
del(ref list);
}

class App
{
private readonly Dictionary<Type, object> delegateMap;
void Add<T>(Action<SomeClass<T>> foo)
{
object tmp;
if (!delegateMap.TryGetValue(typeof(T), out tmp))
{
tmp = new List<Action<SomeClass<T>>>();
delegateMap[typeof(t)] = tmp;
}
List<Action<SomeClass<T>> list = (List<Action<SomeClass<T>>) tmp;
list.Add(foo);
}
void InvokeActions<T>(SomeClass<T> item)
{
object tmp;
if (delegateMap.TryGetValue(typeof(T), out tmp))
{
List<Action<SomeClass<T>> list = (List<Action<SomeClass<T>>) tmp;
foreach (var action in list)
{
action(item);
}
}
}
}
Use Delegates.

Related

C# generic static called wrong while calling

I have a generic extension method like following:
public static class Validator
{
public static IEnumerable<string> Validate<T>(IList<T> items)
{
foreach (var item in items)
{
var result = MyValidator.Validate(item);
if (!result.Any()) continue;
foreach (var validationResult in result)
yield return validationResult.ErrorMessage;
}
}
public static IEnumerable<string> Validate<T>(T item)
{
var result = MyValidator.Validate(item);
if (!result.Any()) yield break;
foreach (var validationResult in result)
yield return validationResult.ErrorMessage;
}
}
But when I call the method for single object or collection it calls Validate(T item);
var item = new Person();
var items = new List<Person>();
var v1 = Validator.Validate(item); // calls Validate<T>(T item)
var v2 = Validator.Validate(items); // calls Validate<T>(T item) but should call Validate<T>(IList<T> items)
I wan to call Validate<T>(IList<T> items) for list.
Why this problem occured?
These extension methods have similar signatures - IList<T> items is T item.
Renaming Validate<T>(IList<T> items) to ValidateList<T>(IList<T> items) or renaming Validate<T>(T item) to ValidateItem<T>(T item) would provide the result you are looking for.
That's because interfaces have lower priority in overloads resolutions than concrete types
As #JonSkeet points out, it may be because the type conversion from T to T is better than List<T> to IList<T>, so the compiler chooses the generic overload.
In your case, you would get the desired behavior by changing the method's parameter from IList<T> to List<T>.
public interface IFoo { }
public class Foo : IFoo { }
public static class Validator
{
public static void Method<T>(T t) { }
public static void Method(object o) { }
public static void Method(IFoo i) { }
}
static void Main()
{
var foo = new Foo();
Validator.Method(foo); // Invokes Method<T>(T t)
object o = foo;
Validator.Method(o); // Explicit object, invokes Method(object o)
IFoo i = foo;
Validator.Method(i); // Explicit interface, invokes Method(IFoo i)
}

Is there a way to make extension-method with List<T>, method(T) as parameters?

I need to make extension method which takes List<> of any type (List<T>) as the first parameter with this(because it is an extension) and a method which takes parameter with same type as the list (Method(T some_parameter)) as the second parameter. Inside of this method I need to make some manipulations of every item in List<T>.
I am not very good in understanding if delegate and Delegate, just can't get it. I tried to use delegates, Delegates, Lambda expressions, but nothing...
static void Main(string[] args)
{
List<item> lisd = new List<item>();
list.CallForEach((List <item> _list) => EXTENDER.Method(_list));
}
public static class EXTENDER
{
public static void Method<T>(List<T> list)
{
//some code
}
public static void CallForEach<T>(this List<T> list, Action<T> action)
{
foreach(var item in list)
{
action(item);
}
}
}
Am i need to use exactly 'Action'?
Send me refs if somebody knows something about similar methods...
For academic purposes
Given
public static class Extension
{
public static void MethodEx<T>(this T item)
{
Console.WriteLine(item);
}
public static void CallForEach<T>(this List<T> list, Action<T> action)
{
foreach (var item in list)
action(item);
}
}
Usage
public static void Method<T>(T item)
{
Console.WriteLine(item);
}
static void Main(string[] args)
{
var list = new List<int>()
{
1,
2,
3,
4,
5,
6
};
list.CallForEach(x => x.MethodEx());
// or you could use a method group
list.CallForEach(Extension.MethodEx);
//or if its not in your extension class
list.CallForEach(Method);
// ForEach is already part of the List class
list.ForEach(x => x.MethodEx());
list.ForEach(Extension.MethodEx);
list.ForEach(Method);
}
Output of all examples
1
2
3
4
5
6

Lambda/Action with a local ref [duplicate]

This question already has answers here:
Cannot use ref or out parameter in lambda expressions
(7 answers)
Closed 4 years ago.
How can I pass a ref to a lambda ? I've seend posts suggesting a delegate but I can't get it to work ..
I tried:
public class State<T>
{
public State() { }
public State(T t) { this.t = t; }
readonly object theLock = new object();
T t;
public void Lock(Action<ref T> action) { lock (theLock) action(ref t); }
}
however this does not compile, I get 'unexpected token ref'
I then tried:
public class State<T>
{
public State() { }
public State(T t) { this.t = t; }
readonly object theLock = new object();
T t;
public delegate void ActionRef<X>(ref X t);
public void Lock(ActionRef<T> action) { lock (theLock) action(ref t); }
}
Which compiles but I'm not able to use it
If I try:
var v = new State<int>(5);
v.Lock(t => t + 1);
I get Parameter 1 must be declared with the 'ref' keyword
If I try:
var v = new State<int>(5);
v.Lock(ref t => t + 1);
I get A ref or out value must be an assignable variable
How can I get this to work ? that is pass an Action to Lock which locks the lock and then calls the lambda with a ref ?
(tested in VS19 community preview .NET Core console app)
(this is different than Cannot use ref or out parameter in lambda expressions as there it's about a lambda using a ref in it's closure)
(credit goes to PetSerAI ..)
I was very close, State<T> is the same:
public class State<T>
{
public State() { }
public State(T t) { this.t = t; }
readonly object theLock = new object();
T t;
public delegate void ActionRef(ref T t);
public void Lock(ActionRef action) { lock (theLock) action(ref t); }
}
but using it is like this:
var s = new State<int>(5);
s.Lock((ref int v) => v=v+3);
For completion here is ReadOnlyState<T>:
public class ReadOnlyState<T>
{
public ReadOnlyState(T t) { this.t = t; }
readonly object theLock = new object();
readonly T t;
public delegate void ActionRef(in T t);
public void Lock(ActionRef action) { lock (theLock) action(in t); }
}
var ros = new ReadOnlyState<int>(5);
ros.Lock((in int v) => {
v.f();
v=2; // does not compile
});

HashMap in C# 'GetEnumerator' [duplicate]

This question already has answers here:
How do I implement IEnumerable<T>
(6 answers)
An example for supporting foreach without implementing IEnumerable
(2 answers)
Closed 5 years ago.
Tried to make a custom HashMap class but im stuck with GetEnumerator.
When i hover over 'test.entrySet()' this shows up
'foreach statement cannot operate on variables of type 'Project.Map' does not contain a public definition for 'GetEnumerator''
My foreach loop looks like this
foreach(Map<string, object> e in test.entrySet()) {
}
My HashMap class looks like this
public class HashMap<K, V> {
private List<object> k = new List<object>();
private List<object> v = new List<object>();
public void put(object k, object v) {
this.k.Add(k);
this.v.Add(v);
}
public object get(object k) {
var i = 0;
foreach (var key in this.k) {
if (k.Equals(key)) {
return this.v.ElementAt(i);
}
i++;
}
return null;
}
public bool exist(object k) {
return this.k.Contains(k);
}
public void clear() {
this.k.Clear();
this.v.Clear();
}
public Map entrySet() {
return null;
}
}
My Map class looks like. I think this class is useless...
public class Map<K,V> {
private List<object> k = new List<object>();
private List<object> v = new List<object>();
public Map(List<object> k, List<object> v) {
this.k = k;
this.v = v;
}
public object getKey() {
return null;
}
public object getValue() {
return null;
}
}
If someone could help me fix this code/give some tips i would be verry glad.
Should look somthing like this
HashMap<string, object test = new HashMap<string, object>();
foreach(Map<string, object> e in test.entrySet()) {
string key = e.getKey();
string value = e.getValue();
}
I don't think you want your getValues() method to return a Map. If you want to get the values in the HashMap, then just return the v object.
public List<object> getValues() {
return v.AsReadOnly();
}
Also a side note, your HashMap class has generic variables but their not used anywhere. You want to replace object with whatever the generic type is.
i.e
private List<K> k = new List<K>();
private List<V> v = new List<V>();
and change your functions
i.e.
public V get(K k) {

Function pointers in C#

I suppose in some ways either (or both) Delegate or MethodInfo qualify for this title. However, neither provide the syntactic niceness that I'm looking for. So, in short, Is there some way that I can write the following:
FunctionPointer foo = // whatever, create the function pointer using mechanisms
foo();
I can't use a solid delegate (ie, using the delegate keyword to declare a delegate type) because there is no way of knowing till runtime the exact parameter list. For reference, here's what I've been toying with in LINQPad currently, where B will be (mostly) user generated code, and so will Main, and hence for nicety to my users, I'm trying to remove the .Call:
void Main()
{
A foo = new B();
foo["SomeFuntion"].Call();
}
// Define other methods and classes here
interface IFunction {
void Call();
void Call(params object[] parameters);
}
class A {
private class Function : IFunction {
private MethodInfo _mi;
private A _this;
public Function(A #this, MethodInfo mi) {
_mi = mi;
_this = #this;
}
public void Call() { Call(null); }
public void Call(params object[] parameters) {
_mi.Invoke(_this, parameters);
}
}
Dictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
public A() {
List<MethodInfo> ml = new List<MethodInfo>(this.GetType().GetMethods());
foreach (MethodInfo mi in typeof(Object).GetMethods())
{
for (int i = 0; i < ml.Count; i++)
{
if (ml[i].Name == mi.Name)
ml.RemoveAt(i);
}
}
foreach (MethodInfo mi in ml)
{
functions[mi.Name] = mi;
}
}
public IFunction this[string function] {
get {
if (!functions.ContainsKey(function))
throw new ArgumentException();
return new Function(this, functions[function]);
}
}
}
sealed class B : A {
public void SomeFuntion() {
Console.WriteLine("SomeFunction called.");
}
}
You say you want to keep the number and type of parameters open, but you can do that with a delgate:
public delegate object DynamicFunc(params object[] parameters);
This is exactly the same thing you currently have. Try this:
class Program
{
static void Main(string[] args)
{
DynamicFunc f = par =>
{
foreach (var p in par)
Console.WriteLine(p);
return null;
};
f(1, 4, "Hi");
}
}
You can think of an instance-method delegate as very similar to your Function class: an object an a MethodInfo. So there's no need to rewrite it.
Also function pointers in C and C++ are not any closer to what you need: they cannot be bound to an object instance and function, and also they are statically typed, not dynamically typed.
If you want to "wrap" any other method in a DynamicFunc delegate, try this:
public static DynamicFunc MakeDynamicFunc(object target, MethodInfo method)
{
return par => method.Invoke(target, par);
}
public static void Foo(string s, int n)
{
Console.WriteLine(s);
Console.WriteLine(n);
}
and then:
DynamicFunc f2 = MakeDynamicFunc(null, typeof(Program).GetMethod("Foo"));
f2("test", 100);
Note that I'm using a static method Foo so I pass null for the instance, but if it was an instance method, I'd be passing the object to bind to. Program happens to be the class my static methods are defined in.
Of course, if you pass the wrong argument types then you get errors at runtime. I'd probably look for a way to design your program so that as much type information is captured at compile time as possible.
Here's another bit of code you could use; Reflection is rather slow, so if you expect your Dynamic function calls to be called frequently, you don't want method.Invoke inside the delegate:
public delegate void DynamicAction(params object[] parameters);
static class DynamicActionBuilder
{
public static void PerformAction0(Action a, object[] pars) { a(); }
public static void PerformAction1<T1>(Action<T1> a, object[] p) {
a((T1)p[0]);
}
public static void PerformAction2<T1, T2>(Action<T1, T2> a, object[] p) {
a((T1)p[0], (T2)p[1]);
}
//etc...
public static DynamicAction MakeAction(object target, MethodInfo mi) {
Type[] typeArgs =
mi.GetParameters().Select(pi => pi.ParameterType).ToArray();
string perfActName = "PerformAction" + typeArgs.Length;
MethodInfo performAction =
typeof(DynamicActionBuilder).GetMethod(perfActName);
if (typeArgs.Length != 0)
performAction = performAction.MakeGenericMethod(typeArgs);
Type actionType = performAction.GetParameters()[0].ParameterType;
Delegate action = Delegate.CreateDelegate(actionType, target, mi);
return (DynamicAction)Delegate.CreateDelegate(
typeof(DynamicAction), action, performAction);
}
}
And you could use it like this:
static class TestDab
{
public static void PrintTwo(int a, int b) {
Console.WriteLine("{0} {1}", a, b);
Trace.WriteLine(string.Format("{0} {1}", a, b));//for immediate window.
}
public static void PrintHelloWorld() {
Console.WriteLine("Hello World!");
Trace.WriteLine("Hello World!");//for immediate window.
}
public static void TestIt() {
var dynFunc = DynamicActionBuilder.MakeAction(null,
typeof(TestDab).GetMethod("PrintTwo"));
dynFunc(3, 4);
var dynFunc2 = DynamicActionBuilder.MakeAction(null,
typeof(TestDab).GetMethod("PrintHelloWorld"));
dynFunc2("extraneous","params","allowed"); //you may want to check this.
}
}
This will be quite a bit faster; each dynamic call will involve 1 typecheck per param, 2 delegate calls, and one array construction due to the params-style passing.

Categories

Resources