Func<T> scope inside class - c#

Why can't I do this?
public int FillModel(int id)
{
// do something...
return 0;
}
public Func<int, int> actiontest = FilleModel;
The code doesn't compile and tells me there is no reference?

As said L.B in his comment you should change:
public Func<int, int> actiontest = FilleModel; //FilleModel doesn't exist
with:
Func<int, int> actiontest = FillModel;
Else if you want to make it public:
public Func<int, int> actiontest;
public myClass(){
actiontest = FillModel;
}
Or:
public Func<int, int> actiontest = FillModel;
private static int FillModel(int id) //private else the delegate doesn't make sense
{
// do something...
return 0;
}

One Important thing, apart from changing:
public Func<int, int> actiontest = FilleModel;
to
Func<int, int> actiontest = FillModel;
You cannot have a direct declaration at the Class level. You can only have such declaration inside some behavior Method or Property setter/getter.

Related

Can not use Func with parameters

I have an example for my problem.
Basically i need to pass a method to another method with parameters included.
public void test() {
var test = Add(Domath(5, 5)); // should be 10
}
public int Domath (int a, int b) {
return a + b;
}
public int Add (Func<int, int, int> math){
return math();
}
It does not work this way and i don‘t know why. This is just a minimalistic example. Is there a way to get this working?
Let's have a look at
public int Add (Func<int, int, int> math){
return math();
}
You can't return return math();: note, that math requires two arguments which are not passed to math(). You can modify Add as
public int Domath (int a, int b){
return a + b;
}
// We are going to add first and second
// with a help of math function
public int Add (int first, int second, Func<int, int, int> math = null) {
// If math is not provided, we use Domath functon
if (math == null)
math = Domath;
// Finally, we call math with required two arguments
return math(first, second);
}
Now you can put
public void test(){
var test = Add(5, 5);
}
Or
public void test(){
var test = Add(5, 5, Domath);
}

Store Func<T> delegates

I am stuck on a problem. I found out that there is no implicit conversion from Func<int> to Func<object> and then especially not from generic Func<T>. I sort of understand why there is no conversion. But I still need to store any functions like the following:
static Dictionary<int, Func<int, object>> funcs = new Dictionary<int, Func<int, object>>();
public static void SetFunction<T>(Func<int, T> f)
{
funcs[42] = f;
}
public static void Main()
{
SetFunction(x => 42);
SetFunction(x => "42");
SetFunction(x => Guid.NewGuid());
}
Is there any way around to store these functions? I don't want to use dynamic.
Also I need to keep original functions. To call them multiple times.
You couldn't use dynamic anyway, it's not what it's for. Instead of thinking about casting, simply add another layer to your function:
public static void SetFunction<T>(Func<T> f)
{
funcs[42] = () => (object)f();
}
You can probably avoid using generics altogether.
static Dictionary<int, Func<object>> funcs = new Dictionary<int, Func<object>>();
public static void SetFunction(Func<object> f)
{
funcs[42] = f;
}
public static void Main()
{
SetFunction(() => 42);
SetFunction(() => "42");
SetFunction(() => Guid.NewGuid());
}
I build an answer based on yours. Especially Blindy's.
I needed some reasoning but you enlightened me enough to build it.
static Dictionary<int, Func<object>> funcs = new Dictionary<int, Func<object>>();
static Random rnd = new Random();
public static void SetFunction<T>(int index, Func<Random, T> f)
{
funcs[index] = () => (object)f(rnd);
}
public static void Main()
{
SetFunction(41, x => x.NextDouble());
SetFunction(42, x => x.Next());
SetFunction(43, _ => "HW");
Console.WriteLine(funcs[41]());
Console.WriteLine(funcs[41]());
Console.WriteLine(funcs[42]());
Console.WriteLine(funcs[42]());
Console.WriteLine(funcs[43]());
Console.WriteLine(funcs[43]());
}
Output:
0.6657498062894446
0.5739200415899605
1762534382
1301357548
HW
HW

Creating a Generic Function to convert an Array into a Dictionary in C#

I have a struct which contains two public variables. I have made an array of that struct, and wish to convert it to a Dictionary.
Here is one such method of accomplishing that:
public class TestClass
{
public struct KeyValuePairs
{
public string variableOne;
public float variableTwo
}
private KeyValuePairs[] keyValuePairs;
private Dictionary<string, float> KeyValuePairsToDictionary()
{
Dictionary<string, float> dictionary = new Dictionary<string, float>();
for(int i = 0; i < keyValuePairs.Length; i++)
{
dictionary.Add(keyValuePairs[i].variableOne, keyValuePairs[i].variableTwo);
}
return dictionary;
}
}
Now, that works for my specific setup, but I wish to try and convert the KeyValuePairsToDictionary() function into a Generic so that it may work across all types.
My first thought, then, was to do something like this:
private Dictionary<T, T> ArrayToDictionary<T>(T[] array)
{
Dictionary<T, T> keyValuePairs = new Dictionary<T, T>();
for(int i = 0; i < array.Length; i++)
{
keyValuePairs.Add(array[i], array[i]); //The problem is right here.
}
return keyValuePairs;
}
As you can probably tell, I can't access the public fields of whatever struct array I am trying to convert into key-value pairs.
With that, how would you suggest I go about performing the generic conversion?
Please note that my specific setup requires that I convert a struct to a dictionary, for I am using the Unity Game Engine.
Thank you.
A generic way of doing this is already implemented in LINQ.
var dict = myArray.ToDictionary(a => a.TheKey);
With your implementation
public struct KeyValuePairs
{
public string variableOne;
public float variableTwo;
}
and an array
KeyValuePairs[] keyValuePairs = ...;
You get
Dictionary<string, KeyValuePairs> dict = keyValuePairs
.ToDictionary(a => a.variableOne);
or alternatively
Dictionary<string, float> dict = keyValuePairs
.ToDictionary(a => a.variableOne, a => a.variableTwo);
Note that the first variant yields a dictionary with values of type KeyValuePairs, while the second one yields values of type float.
According to the conversation, it seems that you are interested on how you would implement this. Here is a suggestion:
public static Dictionary<TKey, TValue> ToDictionary<T, TKey, TValue>(
this IEnumerable<T> source,
Func<T, TKey> getKey,
Func<T, TValue> getValue)
{
var dict = new Dictionary<TKey, TValue>();
foreach (T item in source) {
dict.Add(getKey(item), getValue(item));
}
return dict;
}
Or simply like this, if you want to store the item itself as value
public static Dictionary<TKey, T> ToDictionary<T, TKey>(
this IEnumerable<T> source,
Func<T, TKey> getKey
{
var dict = new Dictionary<TKey, T>();
foreach (T item in source) {
dict.Add(getKey(item), item);
}
return dict;
}
You can use Reflection to achieve that
First of all, add a {get;set;} to the variables to transform them in properties
public struct KeyValuePairs
{
public string variableOne { get; set; }
public float variableTwo { get; set; }
}
Then the method
// T1 -> Type of variableOne
// T2 -> Type of variableTwo
// T3 -> KeyValuesPair type
public static Dictionary<T1, T2> convert<T1,T2,T3>(T3[] data)
{
// Instantiate dictionary to return
Dictionary<T1, T2> dict = new Dictionary<T1, T2>();
// Run through array
for (var i = 0;i < data.Length;i++)
{
// Get 'key' value via Reflection to variableOne
var key = data[i].GetType().GetProperty("variableOne").GetValue(data[i], null);
// Get 'value' value via Reflection to variableTow
var value = data[i].GetType().GetProperty("variableTwo").GetValue(data[i], null);
// Add 'key' and 'value' to dictionary casting to properly type
dict.Add((T1)key, (T2)value);
}
//return dictionary
return dict;
}
I used the following code to test
KeyValuePairs[] val = new KeyValuePairs[5];
val[0] = new KeyValuePairs() { variableOne = "a", variableTwo = 2.4f };
val[1] = new KeyValuePairs() { variableOne = "b", variableTwo = 3.5f };
val[2] = new KeyValuePairs() { variableOne = "c", variableTwo = 4.6f };
val[3] = new KeyValuePairs() { variableOne = "d", variableTwo = 5.7f };
val[4] = new KeyValuePairs() { variableOne = "e", variableTwo = 6.8f };
Dictionary<string, float> dict = convert<string, float,KeyValuePairs>(val);

Get lowered function name from lambda

Is it possible with Roslyn to get to the name of compiler generated lambda methods?
For example imagine the following class:
public sealed class Foo
{
public void Bar()
{
Func<int, int> func = x =>
{
if (x > 0)
{
return x;
}
return -x;
};
}
}
the following Code is generated:
public sealed class Foo
{
[CompilerGenerated]
[Serializable]
private sealed class <>c
{
public static readonly Foo.<>c <>9 = new Foo.<>c();
public static Func<int, int> <>9__0_0;
internal int <Bar>b__0_0(int x)
{
bool flag = x > 0;
int result;
if (flag)
{
result = x;
}
else
{
result = -x;
}
return result;
}
}
public void Bar()
{
Func<int, int> arg_20_0;
if ((arg_20_0 = Foo.<>c.<>9__0_0) == null)
{
Foo.<>c.<>9__0_0 = new Func<int, int>(Foo.<>c.<>9.<Bar>b__0_0);
}
}
}
Roslyn contains the code that is responsible for lowering the lambda into methods with different strategies depending on the circumstance (all here).
But is there any simple way to get the name Foo.<>c.<Bar>b__0_0 if I have the symbol or the SimpleLambdaExpressionSyntax node?
This is obviously implementation specific behavior, so this would require using the same roslyn version the compiler is using, but that'd be an acceptable.
It is not possible with the Roslyn APIs. You can use something like System.Reflection.Metadata to read the IL and find the names if you need to. However it should be said that the names the compiler generates are an implementation detail and they will change.

Cast delegate to Func in C#

I have code:
public delegate int SomeDelegate(int p);
public static int Inc(int p) {
return p + 1;
}
I can cast Inc to SomeDelegate or Func<int, int>:
SomeDelegate a = Inc;
Func<int, int> b = Inc;
but I can't cast Inc to SomeDelegate and after that cast to Func<int, int> with usual way like this:
Func<int, int> c = (Func<int, int>)a; // Сompilation error
How I can do it?
There's a much simpler way to do it, which all the other answers have missed:
Func<int, int> c = a.Invoke;
See this blog post for more info.
SomeDelegate a = Inc;
Func<int, int> b = Inc;
is short for
SomeDelegate a = new SomeDelegate(Inc); // no cast here
Func<int, int> b = new Func<int, int>(Inc);
You can't cast an instance of SomeDelegate to a Func<int, int> for the same reason you can't cast a string to a Dictionary<int, int> -- they're different types.
This works:
Func<int, int> c = x => a(x);
which is syntactic sugar for
class MyLambda
{
SomeDelegate a;
public MyLambda(SomeDelegate a) { this.a = a; }
public int Invoke(int x) { return this.a(x); }
}
Func<int, int> c = new Func<int, int>(new MyLambda(a).Invoke);
Try this:
Func<int, int> c = (Func<int, int>)Delegate.CreateDelegate(typeof(Func<int, int>),
b.Target,
b.Method);
The problem is that:
SomeDelegate a = Inc;
Isn't actually a cast. It's the short-form of:
SomeDelegate a = new SomeDelegate(Inc);
Therefore there's no cast. A simple solution to your problem can be this (in C# 3.0)
Func<int,int> f = i=>a(i);
This works (in C# 4.0 at least - not tried in earlier versions):
SomeDelegate a = Inc;
Func<int, int> c = new Func<int, int>(a);
If you look at the IL, this compiles into exactly the same code as Winston's answer. Here's the IL for the second line of what I just wrote:
ldloc.0
ldftn instance int32 ConsoleApplication1.Program/SomeDelegate::Invoke(int32)
newobj instance void class [mscorlib]System.Func`2<int32,int32>::.ctor(object, native int)
And that's also precisely what you see if you assign a.Invoke into c.
Incidentally, although Diego's solution is more efficient, in that the resulting delegate refers directly to the underlying method rather than going through the other delegate, it doesn't handle multicast delegates correctly. Winston's solution does, because it just defers completely to the other delegate. If you want a direct solution that also handles delegates with multiple targets, you need something a little more complex:
public static TResult DuplicateDelegateAs<TResult>(MulticastDelegate source)
{
Delegate result = null;
foreach (Delegate sourceItem in source.GetInvocationList())
{
var copy = Delegate.CreateDelegate(
typeof(TResult), sourceItem.Target, sourceItem.Method);
result = Delegate.Combine(result, copy);
}
return (TResult) (object) result;
}
This does the right thing for delegates with a single target by the way—it will end up producing just a single delegate of the target type that refers directly to whatever method (and where applicable, object) the input delegate referred to.
You can hack a cast by using a trick where you use the c# equivalent of a c++ union. The tricky part is the struct with two members that have a [FieldOffset(0)]:
[TestFixture]
public class Demo
{
public void print(int i)
{
Console.WriteLine("Int: "+i);
}
private delegate void mydelegate(int i);
[StructLayout(LayoutKind.Explicit)]
struct funky
{
[FieldOffset(0)]
public mydelegate a;
[FieldOffset(0)]
public System.Action<int> b;
}
[Test]
public void delegatetest()
{
System.Action<int> f = print;
funky myfunky;
myfunky.a = null;
myfunky.b = f;
mydelegate a = myfunky.a;
a(5);
}
}
It is the same kind of problem as this:
public delegate int SomeDelegate1(int p);
public delegate int SomeDelegate2(int p);
...
SomeDelegate1 a = new SomeDelegate1(Inc);
SomeDelegate2 b = (SomeDelegate2)a; // CS0030
which is the same kind of problem as:
public class A { int prop { get; set; } }
public class B { int prop { get; set; } }
...
A obja = new A();
B objb = (B)obja; // CS0029
Objects cannot be casted from one type to an unrelated other type, even though the types are otherwise completely compatible. For lack of a better term: an object has type identity that it carries along at runtime. That identity cannot be changed after the object is created. The visible manifestation of this identity is Object.GetType().
I like examples. Here is my example code:
class Program
{
class A
{
public A(D d) { d.Invoke("I'm A!"); }
public delegate string D(string s);
}
class B
{
public delegate string D(string s);
}
static void Main(string[] args)
{
//1. Func to delegates
string F(dynamic s) { Console.WriteLine(s); return s; }
Func<string, string> f = F;
//new A(f);//Error CS1503 Argument 1: cannot convert from 'System.Func<string, string>' to 'ConsoleApp3.Program.A.D'
new A(new A.D(f));//I'm A!
new A(x=>f(x));//I'm A!
Func<string, string> f2 = s => { Console.WriteLine(s); return s; };
//new A(f2);//Same as A(f)
new A(new A.D(f2));//I'm A!
new A(x => f2(x));//I'm A!
//You can even convert between delegate types
new A(new A.D(new B.D(f)));//I'm A!
//2. delegate to F
A.D d = s => { Console.WriteLine(s); return s; };
Func<string, string> f3 = d.Invoke;
f3("I'm f3!");//I'm f3!
Func<string, string> f4 = new Func<string, string>(d);
f4("I'm f4!");//I'm f4!
Console.ReadLine();
}
}
The output is:

Categories