Why events behave differently in this case? - c#

The following program
static IEnumerable<Action> Create()
{
foreach (var i in Enumerable.Range(0, 2))
{
yield return () => { Console.Write(i); };
}
}
static void Main(string[] args)
{
foreach (var func in Create())
{
func();
}
Console.ReadLine();
}
ouputs
01
And this program
static event Action SomethingHappened;
static void Register()
{
foreach (var i in Enumerable.Range(0, 2))
{
SomethingHappened += () => { Console.Write(i); };
}
}
static void Main(string[] args)
{
Register();
SomethingHappened();
Console.ReadLine();
}
outputs
11
Why is that so? How to make the program 2 output 01?

You're capturing the loop variable in your lambda expression. That means when the delegate is finally invoked, it will use the latest value of the variable... which will always be 1. Try this:
foreach (var i in Enumerable.Range(0, 2))
{
int copy = i;
SomethingHappened += () => { Console.Write(copy); };
}
... then read Eric Lippert's blog post about it.

In the second program the variable i is captured by the lambda. To get the correct behavior make a local copy before using it in the lambda. E.g.
foreach (var i in Enumerable.Range(0, 2))
{
var local = i;
SomethingHappened += () => { Console.Write(local); };
}

Related

Make IObservable behave like it is pull-based

I'm working on some old code that does not have IAsyncEnumerable, so I was trying to mimic IAsyncEnumerable behavior with IObservable. The issue is that IObservable is push-based and is giving results in random order.
Here is a very simplified version of what I want to achieve
public static class Program
{
public static void Main()
{
Test().Wait();
Console.ReadLine();
}
private static async Task Test()
{
var l = await GetFirstObservable()
.SelectMany(i =>
{
return GetSecondObservable()
.Select(s => Tuple.Create(i, s));
})
.Take(3)
.ToList();
foreach (var item in l)
{
Console.WriteLine(item);
}
}
private static async Task<T> Echo<T>(T value)
{
Console.WriteLine(value);
await Task.Delay(1);
return value;
}
private static IObservable<int> GetFirstObservable()
{
return Observable.Create(async (IObserver<int> observer, CancellationToken cancellationToken) =>
{
foreach (var i in new [] {1, 2, 3})
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
var e = await Echo(i);
if (cancellationToken.IsCancellationRequested)
{
return;
}
observer.OnNext(e);
}
});
}
private static IObservable<string> GetSecondObservable()
{
return Observable.Create(async (IObserver<string> observer, CancellationToken cancellationToken) =>
{
foreach (var i in new[] { "A", "B" })
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
var e = await Echo(i);
if (cancellationToken.IsCancellationRequested)
{
return;
}
observer.OnNext(i);
}
});
}
}
I want the following results to be in console:
1
A
B
2
A
(1, A)
(1, B)
(2, A)
Instead, the first observable does not wait for the second observable to complete, and I get random results like:
1
A
2
A
3
B
A
B
(1, A)
(2, A)
(1, B)
Is it even possible to achieve this pull-like behavior, or should I just look for something else?

how to BinarySearch in condition?

I have here this code to create ID Randome when calling and then add to the ArrayList, but I want to check if I already have same ID to dont added to ArrayList I have used BinarySearch to check Result
but it look there Something wrong
public delegate void DESetUp();
public static DESetUp IdSetUP = delegate ()
{
ArrayList valID = new ArrayList();
Func<int> getID = () => new Random().Next(1, 5);
int Result = getID();
if (Result == valID.BinarySearch(Result))
{
valID.Add(Result);
Console.WriteLine("AddSuccessful");
}
else
{
Console.WriteLine("AddFailed");
}
foreach (var item in valID)
{
Console.WriteLine("your id is : {0}", item);
}
};
Thank you
try this:
use List instead of ArrayList:
Always you need to sort the values with BinarySearch
List<int> valID = new List<int>();
Func<int> getID = () => new Random().Next(1, 10);
int Result = getID();
// here need to sort the list
valID.Sort();
if (valID.BinarySearch(Result) < 0) // if the position of value is lles than zero the value does not exists
{
valID.Add(Result);
Console.WriteLine("AddSuccessful");
}
else
{
Console.WriteLine("AddFailed");
}
i have reached a great result
i have assisted delegate List
public class MainClass
{
//assist delegate List<int>
public delegate void DESetUp(List<int> DLint);
//assist delegate List<int>
public static DESetUp IdSetUP = delegate (List<int> valID)
{
Func<int> getID = () => new Random().Next(1, 3);
int Result = getID();
// here need to sort the list
valID.Sort();
if (valID.BinarySearch(Result) < 0) // if the position of value is lles than zero the value does not exists
{
valID.Add(Result);
Console.WriteLine("AddSuccessful");
}
else
{
Console.WriteLine("AddFailed");
}
foreach (int item in valID)
{
Console.WriteLine(item);
}
};
static void Main(string[] args)
{
//assist List<int> ID
List<int> ID = new List<int>();
//ADD delegate + List<int> + IdSetUP
IdSetUP(ID);
IdSetUP(ID);
IdSetUP(ID);
IdSetUP(ID);
}
}
thank you all

How to programmatically call a method via Reflection and/or ILGenerator.Emit?

Suppose I have code, that receives list of method calls during runtime:
static void Main(string[] args)
{
var foo = new Foo();
var code0 = "DoThis()";
foo.DynamicCalls(code0);
var code1 = "DoThis(1)";
foo.DynamicCalls(code1);
var code2 = $"DoThat({"Hey"})";
foo.DynamicCalls(code2);
// and so on
}
How do I programmatically invoke these method calls?
This is what I have so far and I feel like I am missing something.
public class Foo
{
public void DoThis()
{
Console.WriteLine($"Doing this {0}");
}
public void DoThis(int count)
{
Console.WriteLine($"Doing this {count}");
}
public void DoThat(string message)
{
Console.WriteLine($"Doing that {message}");
}
public void DynamicCalls(string codeToExecute)
{
EmitCompileAndExecute(codeToExecute); //how?
/*
var targetMethodName = string.Concat(codeToExecute.TakeWhile(z => z != '('));
var stringArgs = string.Concat(codeToExecute.SkipWhile(z => z != '(')
.Skip(1)
.TakeWhile(z => z != ')'))?.Trim()
.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
var methodInfo = this.GetType().GetTypeInfo().GetRuntimeMethods()
.SingleOrDefault(z => z.Name.Equals(targetMethodName, StringComparison.OrdinalIgnoreCase)
& stringArgs.Length == z.GetParameters().Length);
// mi.Invoke(this, stringArgs); // args need to match type!
DynamicMethod dm = new DynamicMethod("foo", null, null);
ILGenerator gen = dm.GetILGenerator();
foreach (string arg in stringArgs)
{
}
*/
}
}

Creating a Custom Predicate

I am new to Lambda's and Delegates. I think my question may not be a good question but i am trying to write a simple Custom Predicate that act just like a Built-In Prediciate.
So i am going to share my Code: Please share with me that where i am going to make a mistake:
Built-In Predicate Code Example:
namespace Built_In_Predicate
{
class Program
{
static void Main(string[] args)
{
List<string> _ListOfPlayers = new List<string>()
{
"James Anderson",
"Broad",
"foo"
};
// Method 1. Predicate and Anonymous function.
Predicate<string> _Predicate = delegate (string someString) { return someString.Length == 3; };
string result = _ListOfPlayers.Find(_Predicate);
Console.WriteLine("Result : {0}", result);
}
}
}
Trying to Create a Custom Predicate (Code):
namespace CustomPredicate
{
class Program
{
// Delegate (Takes some string as a Input and return a Boolean.)
public delegate bool CustomPredicate(string someString);
static void Main(string[] args)
{
List<string> _ListOfPlayers = new List<string>()
{
"James Anderson",
"Broad",
"foo"
};
// Instance of CustomPredicate.
CustomPredicate customPredicate = delegate (string someString) { return someString.Length == 3; };
string result = _ListOfPlayers.Find(customPredicate); // its error.
}
}
}
Help will be appreciated.
Delegates cannot be implicitly converted to each other even if they have the same signature.
Find expects a System.Predicate<T> so you have to give it a System.Predicate<T>.
You can write your own Find method if you want to use your own CustomPredicate.
There are also ways to use your customPredicate variable in the call to Find:
_ListOfPlayers.Find(new Predicate<string>(customPredicate));
_ListOfPlayers.Find(customPredicate.Invoke);
You cannot call Find with something else as the type Predicate. But if you want your own delegate, you could call FirstOrDefault (System.Linq) and then use it.
private delegate bool CustomPredicate (string t);
static void Main(string[] args)
{
List<string> _ListOfPlayers = new List<string>()
{
"James Anderson",
"Broad",
"foo"
};
// Method 1. Predicate and Anonymous function.
CustomPredicate _Predicate = delegate (string someString) { return someString.Length == 3; };
string result = _ListOfPlayers.FirstOrDefault(x => _Predicate(x));
Console.WriteLine("Result : {0}", result);
Console.ReadLine();
}

How to convert a generic or object parameter to a reference type

In this scenario I can't create a base type for both TypeA and TypeB to derive from so I cannot add a Where : TypeBase on the method. I would like to see if there is another way to solve this.
class TypeA
{
int number;
string someString;
}
class TypeB
{
int number;
decimal someDecimal;
}
private List<int> Test(object inputs)
{
List<int> rv = new List<int>();
if (inputs is List<TypeA>)
inputs = (List<TypeA>)inputs;
else if(inputs is List<TypeB>)
inputs = (List<TypeB>)inputs;
foreach(item in inputs)
{
rv.Add(item.number);
}
return rv;
}
private void GenericTest<T>(IEnumerable<T> inputs)
{
MethodInfo property = typeof(T).GetProperty(/*YOUR PROPERTY*/).GetMethod;
foreach (var input in inputs)
{
object value = property.Invoke(input, null);
// Logic
}
}
// To protect it from error
public void Test(IEnumerable<TypeA> inputs)
{
GenericTest(inputs);
}
// To protect it from error
public void Test(IEnumerable<TypeB> inputs)
{
GenericTest(inputs);
}
And by the way why not pass the property name to the Test method ?
You can cast it to an IEnumerable and then do the foreach-loop :
private void Test(object inputs)
{
// you can also change the parameter to IEnumerable to take advantage of compile-time type-checking.
var items = inputs as IEnumerable;
if (items == null)
throw new ArgumentException("inputs");
foreach (var item in items)
{
}
}
If the logic needs to be different for each class, use this :
private void Test(object inputs)
{
var typeAs = inputs as IEnumerable<TypeA>;
if (typeAs != null)
{
foreach (var item in typeAs)
{
}
return;
}
var typeBs = inputs as IEnumerable<TypeB>;
if (typeBs != null)
{
foreach (var item in typeBs)
{
}
return;
}
throw new ArgumentException("inputs");
}
You will do no additional work if you iterate over them independently:
class Program
{
private void Test(object inputs)
{
if (inputs is List<TypeA>)
loop((List<TypeA>) inputs);
if (inputs is List<TypeB>)
loop((List<TypeB>)inputs);
}
private void loop(IEnumerable<TypeA> inputs)
{
foreach (var input in inputs)
{
logic(input.i);
}
}
private void loop(IEnumerable<TypeB> inputs)
{
foreach (var input in inputs)
{
logic(input.i);
}
}
private void logic(int i)
{
// magic happens here
}
}
class TypeA
{
public int i;
}
class TypeB
{
public int i;
}
But for the love of all that is good in the world, please don't do this.
If you really must iterate over the lists in one go for some reason, and you know that Test will only be called with TypeAs and TypeBs, you can handle this with a dynamic type:
class Program
{
static void Main(string[] args)
{
var w = new TypeA {i = 8};
var x = new TypeA {i = 16};
var y = new TypeB {i = 32};
var z = new TypeC(); // don't pass this to Test!
var l = new List<dynamic> {w, x, y};
Test(l);
}
private static void Test(IEnumerable<dynamic> inputs)
{
foreach (var input in inputs)
{
logic(input.i);
}
}
private static void logic(int i)
{
// magic happens here
}
}
class TypeA
{
public int i;
}
class TypeB
{
public int i;
}
class TypeC {} // no members

Categories

Resources