Executing functions conditionally and in parallel - c#

I have some code that currently looks somewhat like this:
Parallel.Invoke(
MyFunction1,
MyFunction2,
MyFunction3,
MyFunction4,
MyFunction5);
This works really well. Now I also have a list of bytes that's passed in as a parameter and that looks like this:
TheList = new List<Byte>{1, 3, 5, 6 };
I want to execute functions based on the content of that list. Let's say that each value of this list is associated to the execution a certain function, like this:
1: MyFunction1,
2: MyFunction2,
...
6: MyFunction6
The actual names of these functions are different.
How do I change my code so that the function calls get executed in parallel and conditionally to the content of the list of bytes? For instance, if the list contains 1 and 5 then the code will execute only MyFunction1 and MyFunction5, both in parallel.
Thanks.

How about this?
Dictionary<byte, Action> actions = new Dictionary<byte, Action>()
{
{ 1, MyFunction1 },
{ 2, MyFunction2 },
...
{ 6, MyFunction6 }
};
List<byte> actionList = new List<byte>() { 1, 3, 5, 6 };
Parallel.Invoke((from action in actionList select actions[action]).ToArray());

Related

Why converting List to Array not referencing in c#?

An array in .Net is a reference type.
Given the two code segments above.
Question: why setting value varible "fixedItem" affects varible "data" in the first segment code, but the second segment code is does not affects
First code segment:
var data = new List<IList<int>>();
data.Add(new List<int>() { 1, 2, 3 });
data.Add(new List<int>() { 3, 8, 6,5 });
data.Add(new List<int>() { 1, 2 });
var fixedItem = data.Last();
fixedItem[1] = 8;
//Result:
//data = {{1,2,3}, {3,8,6,5}, {1,8}}
Second code segment:
var data = new List<IList<int>>();
data.Add(new List<int>() { 1, 2, 3 });
data.Add(new List<int>() { 3, 8, 6,5 });
data.Add(new List<int>() { 1, 2 });
var fixedItem = data.Last().ToArray();
fixedItem[1] = 8;
//Result:
//data = {{1,2,3}, {3,8,6,5}, {1,2}}
docs
according to documentation list.ToArray() method returns array with copies of original list
With the first version, fixedItem is the last item from the outer list, i.e. the third inner list. The same instance. Changing that list will be visible everywhere that list is referenced.
However, in the second version you use ToArray(), which creates a separate copy of the list contents, in a vector. You can do anything you like with your isolated copy - it is a different collection instance (and different collection type). Changing it will only be visible to things that reference the copy. The original list is unaffected because it is a different collection.
This is because with ToArray method, you have created a copy of the original list.
Official documentation
Copies the elements of the List to a new array.
There are many thing involve over here.
When you do ToArray in second segment , it actually create new variable and new collection.
Here you have created list of int, in this integer is value type so when it create new collection it copies those value and assign new memory location.
Now instead of int if you have created some reference type like object of class then if you change value over in one collection affect other. Here variable is new but it still reference the same memory location.
Look at the data types you've created after using Last() from Linq.
You receive two very different data types.
One would be a list while the other is just int[]. They have fairly different functionalities and ways to represent and handle data.

Condense code: SetupSequence returning different values on successive calls

I am testing a method that calls other methods. I have a working test that uses this method to generate my mocked connection object:
private Mock<IDatabaseConnection> MockOutGetControlDocInfoData()
{
Mock<IDatabaseConnection> mockConn = new Mock<IDatabaseConnection>();
List<Mock<IDbCommand>> mockCmds = new List<Mock<IDbCommand>>();
List<long> vals = new List<long>() { 2, 2, 2, 2, 10, 2, 2, 2, 2, 2 };
foreach (long val in vals)
{
mockCmds.Add(CreateMockCmdObjectWithReturnValue(val));
}
mockConn.SetupAllProperties();
mockConn.Setup(c => c.Conn.ConnectionString).Returns("What the heck.");
mockConn.SetupSequence(c => c.CreateCommand(It.IsAny<string>()))
.Returns(mockCmds[0].Object)
.Returns(mockCmds[1].Object)
.Returns(mockCmds[2].Object)
.Returns(mockCmds[3].Object)
.Returns(mockCmds[4].Object)
.Returns(mockCmds[5].Object)
.Returns(mockCmds[6].Object)
.Returns(mockCmds[7].Object)
.Returns(mockCmds[8].Object)
.Returns(mockCmds[9].Object);
return mockConn;
}
I'm not pleased with the SetupSequence Returns, which seems like it ought to be part of a loop, but I don't know how to put more than one Returns into the SetupSequence. Any idea for improvement?
For now at least, I'm fine with manually creating my list of test values.
It shouldn't be relevant, but I can provide the CreateMockCmdObjectWithReturnValue code if needed.
var sequence = mockConn.SetupSequence(c => c.CreateCommand(It.IsAny<string>()));
foreach (var cmd in mockCmds)
{
sequence = sequence.Returns(cmd.Object);
}

using TryGetValue from key and adding not working as intened

I have this code to retrieve a value(integer array) out of a dictionary Then increment one of the elements inside the integer array based on the if statement it is in..
Dictionary<string, int[]> ResultDic = new Dictionary<string, int[]>();
if (TeamOnePoint > TeamTwoPoint)
{
ResultDic.TryGetValue(TeamOneResult, out OutOfDic);
OutOfDic[0]++;
OutOfDic[1]++;
////ResultDic.Remove(TeamOneResult);
////ResultDic.Add(TeamOneResult, OutOfDic);
ResultDic[TeamOneResult] = OutOfDic;;
ResultDic.TryGetValue(TeamTwoResult, out OutOfDic);
OutOfDic[0]++;
OutOfDic[2]++;
////ResultDic.Remove(TeamTwoResult);
////ResultDic.Add(TeamTwoResult, OutOfDic);
ResultDic[TeamTwoResult] = OutOfDic;
}
Now the problem I have is that evertime I read the modified OutOfDic array back into the dictionary into the value part where I specified the Key, every value in the dictionary is modified as well, and not just the key I specified.
The commented part gives the same result as the non commented part. How do I fix this problem to only add the value to the specified key?
The behaviour you've described is only possible if you've added the same array to the dictionary multiple times. Since arrays are reference types every change will affect all values in the dictionay.
So instead of doing this(for example):
Dictionary<string, int[]> ResultDic = new Dictionary<string, int[]>();
int[] array = { 1, 2, 3, 4, 5 };
ResultDic.Add("TeamOne", array);
ResultDic.Add("TeamTwo", array);
You should do this:
int[] array = { 1, 2, 3, 4, 5 };
ResultDic.Add("TeamOne", array);
array = new int[] { 1, 2, 3, 4, 5 };
ResultDic.Add("TeamTwo", array);
Note that it's not necessary to re-assign the array to the dictionary for the same reason (it's a reference type). So you can remove these lines:
ResultDic[TeamOneResult] = OutOfDic;;
// ....
ResultDic[TeamTwoResult] = OutOfDic;

How do I update/add items in/to an IObservable<int> dynamically?

I have an observable collection to which I want to keep feeding objects and they should reach observers even after someone has subscribed to it (which ofcourse is the main aim of an observable). How do I do it?
In the following program, after the subscription has happened I want to feed in 3 more numbers which should reach observers. How do I do this?
I don't want to go via the route where I implement my own Observable class by implementing IObservable<int> and use Publish method? Is there any other way to achieve this?
public class Program
{
static void Main(string[] args)
{
var collection = new List<double> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var observableCollection = collection.ToObservable();
observableCollection.Subscribe(OnNext);
//now I want to add 100, 101, 102 which should reach my observers
//I know this wont' work
collection.Add(100);
collection.Add(101);
collection.Add(102);
Console.ReadLine();
}
private static void OnNext(double i)
{
Console.WriteLine("OnNext - {0}", i);
}
}
This is what I'd do:
var subject = new Subject<double>();
var collection = new List<double> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var observableCollection = collection
.ToObservable()
.Concat(subject); //at the end of the original collection, add the subject
observableCollection.Subscribe(OnNext);
//now I want to add 100, 101, 102 which should reach my observers
subject.OnNext(100);
subject.OnNext(101);
subject.OnNext(102);
Generally, if you can observe whatever is producing the additional input, you'd want to concat that observable, rather than imperatively pushing these values into a subject, but sometimes that's not practical.

How would I achieve a unique result using the Linq method syntax

I have the following data in a table:
e.g. data
0, 'Ford'
1, 'Toyota, Toyota'
2, 'BMW'
3, 'Porsche, Porsche'
4, 'BMW'
I need to place this data in the following type List<Tuple<int, string>> carList so that the results within my list would appear as follows:
0, 'Ford'
1, 'Toyota'
2, 'BMW'
3, 'Porsche'
4, 'BMW'
using the following pseudo code:
while (SQLiteDataReader.Read())
{
carList.Add
(
new Tuple<int, string> (
SQLiteDataReader.GetInt32(0) ,
SQLiteDataReader.GetString(1).[Some extension method to produce unique items]
);
)
}
Note, when there are items with duplication (Toyota, Porsche) , the duplication will always be the same name. i.e you won't get something like 'Toyota, Ford'.
Is there some extension method that would remove the duplication part?
This should do the trick:
SQLiteDataReader.GetString(1).Split(',').First().Trim()
If you're looking to do the whole thing through a linq query, this should work.
If you're just looking to fix your pseudocode, then scottm's solution should work.
LinqDataContext db = new LinqDataContext();
List<Tuple<int, string>> results =
db.Cars.AsEnumerable()
.Select(c => Tuple.Create(c.id, c.Make.Split(',')[0].Trim()))
.ToList();

Categories