private void PerformValuations(DateTime testDate, RegressionEffectivenessTest.RegressionDateWithValues date)
{
var valueDate = new LegacyWCFRateTimeStamp { Type = RateTimeStampType.EndOfDay, TimeStamp = date.ValueDate };
var curveDate = new LegacyWCFRateTimeStamp { Type = RateTimeStampType.EndOfDay, TimeStamp = date.CurveDate };
var shiftDate = new LegacyWCFRateTimeStamp { Type = RateTimeStampType.EndOfDay, TimeStamp = date.ShiftDate };
if (date.NeedHedgeValues)
{
date.HedgeCleanPrice = 0M;
date.HedgeCleanIntrinsicValue = 0M;
foreach (var tran in _hedgeTranQuoteIds)
{
var tranquoteId = tran.TranQuoteId;
CheckAndLoadTrade(testDate, valueDate, shiftDate, curveDate, tran, tranquoteId);
var result = ValueTrade(tranquoteId);
var rtnVal = !result.Succeeded
? HandleFailure(tranquoteId, shiftDate, curveDate, result, valueDate)
: CreateAccountingValuation(valueDate, result);
date.HedgeCleanIntrinsicValue += rtnVal.IntrinsicValue - rtnVal.AccruedInterest.GetValueOrDefault(0);
date.HedgeCleanPrice += rtnVal.CleanPrice;
}
}
So I'm trying to run a Parallel.ForEach on this method. There were a couple of things that I was worried about. The first one is within the CheckAndLoadTrade method, it accesses a private Dictionary of the class to possibly add an item to it if it isn't there, and then the ValueTrade method gets an item from this dictionary.
If I parallel this out, am I going to run into any thread safety issues with the dictionary being accessed? Or possibly anything else I didn't notice? All other method calls use variables defined in their own scope, it's really just this one Dictionary that I am worried about. Should I throw a lock before and after the actual dictionary access happens?
What part are you trying to parallelize? The foreach loop?
If you can, use a ConcurrentDictionary. within CheckAndLoadTrade. Another concern is what code runs when the trade is not in the dictionary. Is the "loadtrade" code thread-safe?
Related
How can I reduce execution time for this code block?
public static IEnumerable<ListviewDataViewModel> GetModelsList<T>(this IEnumerable<T> modelsList
, IEnumerable<ListviewColumnViewModel> modelsColumn
, Action<ListviewDataViewModel, T> listVwItemCallback = null) where T : class
{
List<ListviewDataViewModel> listItms = null;
if (modelsColumn == null || !modelsColumn.Any())
return null;
foreach (var d in modelsList)
{
var li = new ListviewDataViewModel();
foreach (var c in modelsColumn)
{
var _col = string.Empty;
var type = d.GetType();
var prp = type.GetProperty(c.ModelProperty);
if (prp != null)
_col = (prp.GetValue(d) ?? "").ToString();
li.ColumnItem.Add(_col);
}
// call the callback if available.
listVwItemCallback?.Invoke(li, d);
if (listItms == null)
listItms = new List<ListviewDataViewModel>();
listItms.Add(li);
}
return listItms;
}
When I have hundreds records in modelList, It takes about a minute to get the results. I would like to reduce the execution time to half. Can someone guide me with this?
Cache the result of type.GetProperty(c.ModelProperty); once for each column and stop using reflection for every single row and every single column.
And in general, you should avoid reflection altogether. There are much better ways to do this with tools ranging from T4 templates to incremental source generators.
i am differentiating 1 million list of object with another 1 million list of object.
i am using for , foreach but it takes too much of time to iterate those list.
can any one help me best way to do this
var SourceList = new List<object>(); //one million
var TargetList = new List<object>()); // one million
//getting data from database here
//SourceList with List of one million
//TargetList with List of one million
var DifferentList = new List<object>();
//ForEach
SourceList.ToList().ForEach(m =>
{
if (!TargetList.Any(s => s.Name == m.Name))
DifferentList.Add(m);
});
//for
for (int i = 0; i < SourceList .Count; i++)
{
if (!TargetList .Any(s => s == SourceList [i].Name))
DifferentList .Add(SourceList [i]);
}
I think it seems like a bad idea but IEnumerable magic will help you.
For starters, simplify your expression. It looks like this:
var result = sourceList.Where(s => targetList.Any(t => t.Equals(s)));
I recommend making a comparison in the Equals method:
public class CompareObject
{
public string prop { get; set; }
public new bool Equals(object o)
{
if (o.GetType() == typeof(CompareObject))
return this.prop == ((CompareObject)o).prop;
return this.GetHashCode() == o.GetHashCode();
}
}
Next add AsParallel. This can both speed up and slow down your program. In your case, you can add ...
var result = sourceList.AsParallel().Where(s => !targetList.Any(t => t.Equals(s)));
CPU 100% loaded if you try to list all at once like this:
var cnt = result.Count();
But it’s quite tolerable to work if you get the results in small portions.
result.Skip(10000).Take(10000).ToList();
Full code:
static Random random = new Random();
public class CompareObject
{
public string prop { get; private set; }
public CompareObject()
{
prop = random.Next(0, 100000).ToString();
}
public new bool Equals(object o)
{
if (o.GetType() == typeof(CompareObject))
return this.prop == ((CompareObject)o).prop;
return this.GetHashCode() == o.GetHashCode();
}
}
void Main()
{
var sourceList = new List<CompareObject>();
var targetList = new List<CompareObject>();
for (int i = 0; i < 10000000; i++)
{
sourceList.Add(new CompareObject());
targetList.Add(new CompareObject());
}
var stopWatch = new Stopwatch();
stopWatch.Start();
var result = sourceList.AsParallel().Where(s => !targetList.Any(t => t.Equals(s)));
var lr = result.Skip(10000).Take(10000).ToList();
stopWatch.Stop();
Console.WriteLine(stopWatch.Elapsed);
}
Update
I remembered what you can use Hashtable.Choos unique values from targetList and from sourceList next fill out the result whose values are not targetList.
Example:
static Random random = new Random();
public class CompareObject
{
public string prop { get; private set; }
public CompareObject()
{
prop = random.Next(0, 1000000).ToString();
}
public new int GetHashCode() {
return prop.GetHashCode();
}
}
void Main()
{
var sourceList = new List<CompareObject>();
var targetList = new List<CompareObject>();
for (int i = 0; i < 10000000; i++)
{
sourceList.Add(new CompareObject());
targetList.Add(new CompareObject());
}
var stopWatch = new Stopwatch();
stopWatch.Start();
var sourceHashtable = new Hashtable();
var targetHashtable = new Hashtable();
foreach (var element in targetList)
{
var hash = element.GetHashCode();
if (!targetHashtable.ContainsKey(hash))
targetHashtable.Add(element.GetHashCode(), element);
}
var result = new List<CompareObject>();
foreach (var element in sourceList)
{
var hash = element.GetHashCode();
if (!sourceHashtable.ContainsKey(hash))
{
sourceHashtable.Add(hash, element);
if(!targetHashtable.ContainsKey(hash)) {
result.Add(element);
}
}
}
stopWatch.Stop();
Console.WriteLine(stopWatch.Elapsed);
}
Scanning the target list to match the name is an O(n) operation, thus your loop is O(n^2). If you build a HashSet<string> of all the distinct names in the target list, you can check whether a name exists in the set in O(1) time using the Contains method.
//getting data from database here
You are getting the data out of a system that specializes in matching and sorting and filtering data, into your RAM that by default cannot yet do that task at all. And then you try to sort, filter and match yourself.
That will fail. No matter how hard you try, it is extremely unlikely that your computer with a single programmer working at a matching algorithm will outperform your specialized piece of hardware called a database server at the one operation this software is supposed to be really good at that was programmed by teams of experts and optimized for years.
You don't go into a fancy restaurant and ask them to give you huge bags of raw ingredients so you can throw them into a big bowl unpeeled and microwave them at home. No. You order a nice dish because it will be way better than anything you could do yourself.
The simple answer is: Do not do that. Do not take the raw data and rummage around in it for hours. Leave that job to the database. It's the one thing it's supposed to be good at. Use it's power. Write a query that will give you the result, don't get the raw data and then play database yourself.
Foreach performs a null check before each iteration, so using a standard for loop will provide slightly better performance that will be hard to beat.
If it is taking too long, can you break down the collection into smaller sets and/or process them in parallel?
Also you could look a PLinq (Parallel Linq) using .AsParallel()
Other areas to improve are the actual comparison logic that you are using, also how the data is stored in memory, depending on your problem, you may not have to load the entire object into memory for every iteration.
Please provide a code example so that we can assist further, when such large amounts of data are involved performance degredation is to be expected.
Again depending on the time that we are talking about here, you could upload the data into a database and use that for the comparison rather than trying to do it natively in C#, this type of solution is better suited to data sets that are already in a database or where the data changes much less frequently than the times you need to perform the comparison.
public class TestObject
{
string TestValue { get; set; }
bool IsDuplicate { get; set; }
}
List<TestObject> testList = new List<TestObject>
{
new TestObject { TestValue = "Matt" },
new TestObject { TestValue = "Bob" },
new TestObject { TestValue = "Alice" },
new TestObject { TestValue = "Matt" },
new TestObject { TestValue = "Claire" },
new TestObject { TestValue = "Matt" }
};
Imagine testList is actually millions of objects long.
What's the fastest way to ensure that two of those three TestObjects with TestValue of Matt gets its IsDuplicate set to true? No matter how may instances of a given value there are, only one should come out of the process with IsDuplicate of false.
I am not averse to doing this via threading. And the collection doesn't have to be a list if converting it to another collection type is faster.
I need to keep duplicates and mark them as such, not remove them from the collection.
To expand, this is (as you might imagine) a simple expression of a much more complex problem. The objects in question already have an ordinal which I can use to order them.
After matching initial duplicates on exact string equality, I'm going to have to go back through the collection again and re-try the remainder using some fuzzy matching logic. The collection that exists at the start of this process won't be changed during the deduplication, or afterwards.
Eventually the original collection is going to be written out to a file, with likely duplicates flagged.
As others mentioned, the correct approach here would be to use the HashSet class.
var hashSet = new HashSet<string>();
foreach (var obj in testList)
{
if (!hashSet.Add(obj.TestValue))
{
obj.IsDuplicate = true;
}
}
When you add a value first time to the HashSet, it adds successfully and HashSet.Add() method returns true so you don't make any changes to the item. When you're trying to add it second time, HashSet.Add() returns false and you mark your item as a duplicate.
The list will have the following state after finishing running our marking duplicates method:
Matt
Bob
Alice
Claire
Matt DUPLICATE
This is probably quite performant:
foreach (var dupe in testList.GroupBy(x => x.TestValue).SelectMany(g => g.Skip(1)))
dupe.IsDuplicate = true;
[EDIT] This method turns out to be about a third of the speed of the accepted answer above, so that one should be used. This answer is merely of academic interest.
Probably I would go to check for the duplicates while building the collection of the TestValue to avoid looping two times on millions of elements. If this scenario is possible then I would use a Dictionary<string, List<TestValue>>
Dictionary<string, List<TestValue>> myList = new Dictionary<string, List<TestValue>>();
while(NotEndOfData())
{
TestValue obj = GetTestValue();
if(myList.ContainsKey(obj.Name))
{
obj.IsDuplicate = true;
myList[obj.Name].Add(obj);
}
else
{
obj.IsDuplicate = false;
myList.Add(obj.Name, new List<TestValue>() { obj};
}
}
SortedSet<string> sorted = new SortedSet<string>();
for (int i = 0; i < testList.Count; i++)
testList[i].IsDuplicate = !sorted.Add(testList[i].TestValue);
As you have allowed in the question, I'd change testList to be an array instead of a list, to make indexer faster.
Since you indicated that you have a property that keeps the ordinal of your items. We can use that property to reset the sort order back to its original after marking our items as duplicates.
The code below is self-explainatory. But just let me know in case you need any further explaination.
I have assumed that the property name is SortOrder. Modify the code accordingly.
void MarkDuplicates()
{
testList = testList.OrderBy(f => f.TestValue).ThenBy(f => f.SortOrder).ToList();
for (int i = 1; i < testList.Count; i++)
{
if (testList[i].TestValue == testList[i - 1].TestValue) testList[i].IsDuplicate = true;
}
testList = testList.OrderBy(f => f.SortOrder).ToList();
}
I'm not a performance expert. But you can time the various solutions provided here and check the performance for yourself.
I created the following class:
class TrdRamValue
{
double Value = 0.0;
TrdState State = TrdState.Ok;
DateTime dt = DateTime.UtcNow;
}
I then created a list with this class to store the information:
List<TrdRamValue> DMSrows = new List<TrdRamValue> ();
And I use the following inside a Handler to constantly insert values every second:
string[] value = new string[3];
value[0] = val;
value[1] = val.Error.ToString ();
value[2] = val.Time.ToString ();
DMSrows.AddRange (value);
But in code it keeps saying that I have an error in my argument, that I can't convert string[] to System.Collections.Generic.IEnumerable.
I'm completely lost on this one...
ANSWER:
It was just a minor error from my part, and I also took huMpty duMpty suggestion since he's completely right, I don't need that string array.
All I had to do was make the class and the variables inside public in order to do what huMpty duMpty told me.
public class TrdRamValue
{
public double Value = 0.0;
public TrdState State = TrdState.Ok;
public DateTime dt = DateTime.UtcNow;
}
Then apply huMpty duMpty suggestion:
TrdRamValue value = new TrdRamValue() ;
value.Value = val;
if (!val.Error) {
value.State = TrdState.Ok;
}
else if (val.Error) value.State = TrdState.Error;
value.dt = val.Time;
DMSrows.Add (value);
Your List is not a List<string> but a List<TrdRamValue>. Therefore, you cannot add strings to the list. You can only add instances of TrdRamValue, or, in the case of AddRange, an IEnumerable (such as an array) of TrdRamValue.
So you can do this:
TrdRamValue toAdd = new TrdRamValue { Value = val, State = ..., dt = ... };
dmsRows.Add(toAdd);
(btw naming a variable DMSRows does not fit with the .net naming conventions).
You're trying to add strings to a list of TrdRamValue objects. Your list is type-safe, which means you are only allowed to add TrdRamValue objects to it.
Not sure why you need string array here.
Also you don't need List.AddRange here since you adding one item. You can use List.Add
DMSrows.Add(new TrdRamValue{
Value =val,
State =val.Error,
dt =val.Time
});
I've got a work around for this issue, but I'm trying to figure out why it works . Basically, I'm looping through a list of structs using foreach. If I include a LINQ statement that references the current struct before I call a method of the struct, the method is unable to modify the members of the struct. This happens regardless of whether the LINQ statement is even called. I was able to work around this by assigning the value I was looking for to a variable and using that in the LINQ, but I would like to know what is causing this. Here's an example I created.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeirdnessExample
{
public struct RawData
{
private int id;
public int ID
{
get{ return id;}
set { id = value; }
}
public void AssignID(int newID)
{
id = newID;
}
}
public class ProcessedData
{
public int ID { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<ProcessedData> processedRecords = new List<ProcessedData>();
processedRecords.Add(new ProcessedData()
{
ID = 1
});
List<RawData> rawRecords = new List<RawData>();
rawRecords.Add(new RawData()
{
ID = 2
});
int i = 0;
foreach (RawData rawRec in rawRecords)
{
int id = rawRec.ID;
if (i < 0 || i > 20)
{
List<ProcessedData> matchingRecs = processedRecords.FindAll(mr => mr.ID == rawRec.ID);
}
Console.Write(String.Format("With LINQ: ID Before Assignment = {0}, ", rawRec.ID)); //2
rawRec.AssignID(id + 8);
Console.WriteLine(String.Format("ID After Assignment = {0}", rawRec.ID)); //2
i++;
}
rawRecords = new List<RawData>();
rawRecords.Add(new RawData()
{
ID = 2
});
i = 0;
foreach (RawData rawRec in rawRecords)
{
int id = rawRec.ID;
if (i < 0)
{
List<ProcessedData> matchingRecs = processedRecords.FindAll(mr => mr.ID == id);
}
Console.Write(String.Format("With LINQ: ID Before Assignment = {0}, ", rawRec.ID)); //2
rawRec.AssignID(id + 8);
Console.WriteLine(String.Format("ID After Assignment = {0}", rawRec.ID)); //10
i++;
}
Console.ReadLine();
}
}
}
Okay, I've managed to reproduce this with a rather simpler test program, as shown below, and I now understand it. Admittedly understanding it doesn't make me feel any less nauseous, but hey... Explanation after code.
using System;
using System.Collections.Generic;
struct MutableStruct
{
public int Value { get; set; }
public void AssignValue(int newValue)
{
Value = newValue;
}
}
class Test
{
static void Main()
{
var list = new List<MutableStruct>()
{
new MutableStruct { Value = 10 }
};
Console.WriteLine("Without loop variable capture");
foreach (MutableStruct item in list)
{
Console.WriteLine("Before: {0}", item.Value); // 10
item.AssignValue(30);
Console.WriteLine("After: {0}", item.Value); // 30
}
// Reset...
list[0] = new MutableStruct { Value = 10 };
Console.WriteLine("With loop variable capture");
foreach (MutableStruct item in list)
{
Action capture = () => Console.WriteLine(item.Value);
Console.WriteLine("Before: {0}", item.Value); // 10
item.AssignValue(30);
Console.WriteLine("After: {0}", item.Value); // Still 10!
}
}
}
The difference between the two loops is that in the second one, the loop variable is captured by a lambda expression. The second loop is effectively turned into something like this:
// Nested class, would actually have an unspeakable name
class CaptureHelper
{
public MutableStruct item;
public void Execute()
{
Console.WriteLine(item.Value);
}
}
...
// Second loop in main method
foreach (MutableStruct item in list)
{
CaptureHelper helper = new CaptureHelper();
helper.item = item;
Action capture = helper.Execute;
MutableStruct tmp = helper.item;
Console.WriteLine("Before: {0}", tmp.Value);
tmp = helper.item;
tmp.AssignValue(30);
tmp = helper.item;
Console.WriteLine("After: {0}", tmp.Value);
}
Now of course each time we copy the variable out of helper we get a fresh copy of the struct. This should normally be fine - the iteration variable is read-only, so we'd expect it not to change. However, you have a method which changes the contents of the struct, causing the unexpected behaviour.
Note that if you tried to change the property, you'd get a compile-time error:
Test.cs(37,13): error CS1654: Cannot modify members of 'item' because it is a
'foreach iteration variable'
Lessons:
Mutable structs are evil
Structs which are mutated by methods are doubly evil
Mutating a struct via a method call on an iteration variable which has been captured is triply evil to the extent of breakage
It's not 100% clear to me whether the C# compiler is behaving as per the spec here. I suspect it is. Even if it's not, I wouldn't want to suggest the team should put any effort into fixing it. Code like this is just begging to be broken in subtle ways.
Ok. We definitely have an issues here but I suspect that this issue not with closures per se but with foreach implementation instead.
C# 4.0 specification stated (8.8.4 The foreach statement) that "the iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement". That's why we can't change loop variable or increment it's property (as Jon already stated):
struct Mutable
{
public int X {get; set;}
public void ChangeX(int x) { X = x; }
}
var mutables = new List<Mutable>{new Mutable{ X = 1 }};
foreach(var item in mutables)
{
// Illegal!
item = new Mutable();
// Illegal as well!
item.X++;
}
In this regard read-only loop variables behave almost exactly the same as any readonly field (in terms of accessing this variable outside of the constructor):
We can't change readonly field outside of the constructor
We can't change property of the read-only field of value type
We're treating readonly fields as values that leads to using a temporary copy every time we accessing readonly field of value type.
.
class MutableReadonly
{
public readonly Mutable M = new Mutable {X = 1};
}
// Somewhere in the code
var mr = new MutableReadonly();
// Illegal!
mr.M = new Mutable();
// Illegal as well!
mr.M.X++;
// Legal but lead to undesired behavior
// becaues mr.M.X remains unchanged!
mr.M.ChangeX(10);
There is a plenty of issues related to mutable value types and one of them related to the last behavior: changing readonly struct via mutator method (like ChangeX) lead to obscure behavior because we'll modify a copy but not an readonly object itself:
mr.M.ChangeX(10);
Is equivalent to:
var tmp = mr.M;
tmp.ChangeX(10);
If loop variable treated by the C# compiler as a read-only local variable, than its seems reasonable to expect the same behavior for them as for read-only fields.
Right now loop variable in the simple loop (without any closures) behaves almost the same as a read-only field except copying it for every access. But if code changes and closure comes to play, loop variable starts behaving like pure read-only variable:
var mutables = new List<Mutable> { new Mutable { X = 1 } };
foreach (var m in mutables)
{
Console.WriteLine("Before change: {0}", m.X); // X = 1
// We'll change loop variable directly without temporary variable
m.ChangeX(10);
Console.WriteLine("After change: {0}", m.X); // X = 10
}
foreach (var m in mutables)
{
// We start treating m as a pure read-only variable!
Action a = () => Console.WriteLine(m.X));
Console.WriteLine("Before change: {0}", m.X); // X = 1
// We'll change a COPY instead of a m variable!
m.ChangeX(10);
Console.WriteLine("After change: {0}", m.X); // X = 1
}
Unfortunately I can't find strict rules how read-only local variables should behave but its clear that this behavior is different based on loop body: we're not copying to locals for every access in simple loop, but we DO this if the loop body closes over loop variable.
We all know that Closing over loop variable considered harmful and that loop implementation was changed in the C# 5.0. Simple way to fix that old issue in pre C# 5.0 era was introducing local variable, but interesting that introducing local variable in this our case will change behavior as well:
foreach (var mLoop in mutables)
{
// Introducing local variable!
var m = mLoop;
// We're capturing local variable instead of loop variable
Action a = () => Console.WriteLine(m.X));
Console.WriteLine("Before change: {0}", m.X); // X = 1
// We'll roll back this behavior and will change
// value type directly in the closure without making a copy!
m.ChangeX(10); // X = 10 !!
Console.WriteLine("After change: {0}", m.X); // X = 1
}
Actually this means that C# 5.0 has very subtle breaking change because no one will introduce a local variable any more (and even tools like ReSharper stops warning about it in VS2012 because its not an issue).
I'm OK with both behaviors but inconsistency seems strange.
I suspect this has to do with how lambda expressions are evaluated. See this question and its answer for more details.
Question:
When using lambda expressions or anonymous methods in C#, we have to be wary of the access to modified closure pitfall. For example:
foreach (var s in strings)
{
query = query.Where(i => i.Prop == s); // access to modified closure
Due to the modified closure, the above code will cause all of the Where clauses on the query to be based on the final value of s.
Answer:
This is one of the worst "gotchas" in C#, and we are going to take the breaking change to fix it. In C# 5 the foreach loop variable will be logically inside the body of the loop, and therefore closures will get a fresh copy every time.
Just to accomplish Sergey's post, I wanna to add following example with manual closure, that demonstrates compiler's behavior. Of course compiler might have any other implementation that satisfies readonly requirement of captured within foreach statement variable.
static void Main()
{
var list = new List<MutableStruct>()
{
new MutableStruct { Value = 10 }
};
foreach (MutableStruct item in list)
{
var c = new Closure(item);
Console.WriteLine(c.Item.Value);
Console.WriteLine("Before: {0}", c.Item.Value); // 10
c.Item.AssignValue(30);
Console.WriteLine("After: {0}", c.Item.Value); // Still 10!
}
}
class Closure
{
public Closure(MutableStruct item){
Item = item;
}
//readonly modifier is mandatory
public readonly MutableStruct Item;
public void Foo()
{
Console.WriteLine(Item.Value);
}
}
This might solve your issue. It swaps out foreach for a for and makes the struct immutable.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeirdnessExample
{
public struct RawData
{
private readonly int id;
public int ID
{
get{ return id;}
}
public RawData(int newID)
{
id = newID;
}
}
public class ProcessedData
{
private readonly int id;
public int ID
{
get{ return id;}
}
public ProcessedData(int newID)
{
id = newID;
}
}
class Program
{
static void Main(string[] args)
{
List<ProcessedData> processedRecords = new List<ProcessedData>();
processedRecords.Add(new ProcessedData(1));
List<RawData> rawRecords = new List<RawData>();
rawRecords.Add(new RawData(2));
for (int i = 0; i < rawRecords.Count; i++)
{
RawData rawRec = rawRecords[i];
int id = rawRec.ID;
if (i < 0 || i > 20)
{
RawData rawRec2 = rawRec;
List<ProcessedData> matchingRecs = processedRecords.FindAll(mr => mr.ID == rawRec2.ID);
}
Console.Write(String.Format("With LINQ: ID Before Assignment = {0}, ", rawRec.ID)); //2
rawRec = new RawData(rawRec.ID + 8);
Console.WriteLine(String.Format("ID After Assignment = {0}", rawRec.ID)); //2
i++;
}
rawRecords = new List<RawData>();
rawRecords.Add(new RawData(2));
for (int i = 0; i < rawRecords.Count; i++)
{
RawData rawRec = rawRecords[i];
int id = rawRec.ID;
if (i < 0)
{
List<ProcessedData> matchingRecs = processedRecords.FindAll(mr => mr.ID == id);
}
Console.Write(String.Format("With LINQ: ID Before Assignment = {0}, ", rawRec.ID)); //2
rawRec = new RawData(rawRec.ID + 8);
Console.WriteLine(String.Format("ID After Assignment = {0}", rawRec.ID)); //10
i++;
}
Console.ReadLine();
}
}
}