I have the following method. When the Writeline Methods are calling, missing results arise. The result of
the second Writeline must true otherwise, it is false, could you please advise me?
public static void IsGreater()
{
var biggerThanNumber = new Predicate<int>[10];
for (int index = 0; index < biggerThanNumber.Length; ++index)
{
biggerThanNumber[index] = value => value > index;
}
Console.WriteLine(biggerThanNumber[5](20)); //True
Console.WriteLine(biggerThanNumber[5](6)); //False
}
Change the method to copy loop variable into a local reference to avoid lambda closure issue in a loop. In your method value of index is always 10 hence second the console is returning false. For more info check this post
public static void IsGreater()
{
var biggerThanNumber = new Predicate<int>[10];
for (int index = 0; index < biggerThanNumber.Length; ++index)
{
int localCopy = index;
biggerThanNumber[index] = value => value > localCopy;
}
Console.WriteLine(biggerThanNumber[5](20)); //True
Console.WriteLine(biggerThanNumber[5](6)); //True
}
Related
Hey I'm in a situation where I have a for loop that does some stuff and I want to make a line of code either call a function passing in an array indexed by the for loops index, or run a single (not array) variable for every call of that function, I know I could do that by putting an if statement inside the for loop but i'd be repeating the same if statement over and over getting the same result. So is there a way good way I can run the if statement before the for loop and the result of that if statement run the same for loop but that one call passes in the array or the variable?
Code Example
for (int i = 0; i < CurrentVerticalList.Count; i++)
{
GuiGeneral CGroup = CurrentVerticalList[i];
CGroup.ResizeUsingStandard(ForcedResize[i]); //I want the condition before the for
//loop to have ForcedResize[i] here if
//true and another variable here of the
//same type but not an array if false.
for (int j = 0; j < 2; j++)
{
GlobalListIndex[j]++;
}
CGroup.MoveElementTo(CCoord, false);
CCoord.y += CGroup.ElementRect.WidthHeight.y;
}
Here you go, moving your condition check out of your for loop:
Func<int, double> GetResizeFromForcedResize = (index => ForcedResize[index]);
Func<int, double> GetResizeFromVariable = (index => fixVariable);
var GetResizeValue = condition? GetResizeFromForcedResize : GetResizeFromVariable;
for (int i = 0; i < CurrentVerticalList.Count; i++)
{
GuiGeneral CGroup = CurrentVerticalList[i];
CGroup.ResizeUsingStandard(GetResizeValue(i));
for (int j = 0; j < 2; j++)
{
GlobalListIndex[j]++;
}
CGroup.MoveElementTo(CCoord, false);
CCoord.y += CGroup.ElementRect.WidthHeight.y;
}
Edit: Wanted to let you know that the other answers here are still doing a check at every iteration, but not this one.
Eh, hard to understand the question to me but i recon what you want is something along these lines, could've helped with more types supplied, but you could make the intend achievable using a local function:
ForcedResizeArrayType other = new object(); //TODO: Define return type
bool condition = ResolveCondition(); //TODO: Define condition to be true or false
ForcedResizeArrayType GetOneOr(int i, bool condition,
ForcedResizeArrayType[] forcedResizeArray)
{
return condition ? forcedResizeArray[i] : other;
}
for (int i = 0; i < CurrentVerticalList.Count; i++)
{
CGroup.ResizeUsingStandard(GetOneOr(i, condition, ForcedResize));
}
It varies from week to week if i love or hate those local functions, but they have uses
I'm new here and I tried looking through old questions but I am new to c# as well, and I am finding it difficult to solve my problem below:
if (File.Exists(#"C:\ESC\Impostazioni.txt"))
{
TextReader lettore_file = new StreamReader(#"C:\ESC\Impostazioni.txt");
String opzioni = lettore_file.ReadLine();
int i;
for (i = 0; i < opzioni.Length; i++) <----here, indicating "i=0"
{
if (opzioni[i] == '-')
{
char[] coloregenerale = new char[i];
for (int j = 0; j < i; j++)
coloregenerale[j] = opzioni[j];
break;
You should put a check to see if the string value is null or empty before trying to loop through each character, like this:
if(!String.IsNullOrEmpty(opzioni))
{
// Put loop through character logic here
}
You need to debug through and find out if your opzioni string is a null reference after your call to String opzioni = lettore_file.ReadLine();
Also, you should probably declare i within the for loop, instead of before it, like shown below.
for (int i = 0; i < opzioni.Length; i++)
There are several wrongs inside that code:
You're missing a using statement.
You're not checking the result of StreamReader.ReadLine.
It looks like you're reimplementing string.Substring.
Sample:
if (File.Exists(#"C:\ESC\Impostazioni.txt"))
{
using (var letterFile = new StreamReader(#"C:\ESC\Impostazioni.txt"))
{
var opzioni = letterFile.ReadLine();
if(string.IsNullOrWhiteSpace(opzioni))
{
// end of file
}
var dashIndex = opzioni.IndexOf("-");
string coloregenerale = dashIndex > -1
? opzioni.Substring(0, dashIndex)
: opzioni;
}
}
If your null reference exception is occurring on the indicated line, the culprit is probably the opzioni variable. If the earlier call to lettore_file.ReadLine() returns null, opzioni will be null when you try to get it's length in the for loop. That will throw the exception you're experiencing. A solution is to check that variable for null before entering the loop
The opzioni may have the chances of null value on that particular index, better handle inside of that line with IsNullorEmpty Condition
char[] coloregenerale = new char[i];
for (int j = 0; j < i; j++)
{
if( String.IsNullOrEmpty(opzioni[j] == false ) // This is mandatory check at this place
coloregenerale[j] = opzioni[j];
}
I have the following method that sorts a list of binding source indices and puts their corresponding objects into an array. I have also tried using Array.Sort() and neither works, the code within the foreach loop never gets called. I have tested that the variable int[] indices is neither empty nor null.
internal void Foo(int[] indices)
{
var bar = new Object[indices.length];
int i = 0;
foreach (int index in indices.OrderBy(x => x))
{
// this block never gets called
bar[i] = BindingSource[index];
i++;
}
}
You can try this:
var bar = indices.OrderBy(x => x).Select(x => BindingSource[x]).ToArray();
But I think that your code should work though I think that you could improve it using a for-loop instead of a foreach.
internal void Foo(int[] indices)
{
var bar = new Object[indices.Length];
indices = indices.OrderBy(x => x);
for(int i = 0; i < indices.Length; i++)
bar[i] = BindingSource[indices[i]];
}
Another thing, you should get sure that the indices.Length doesn't equal 0 so I think that indices is empty.
PS : C# is case-sensitive so indices.length in your code should be indices.Length .
The issue is that OrderBy was not returning the sorted array, as I had assumed it did. The following is my solution.
internal void Foo(int[] indices)
{
var bar = new Object[indices.Length];
int i = 0;
indices = indices.OrderBy(x => x).ToArray();
foreach (int index in indices)
{
// now this block gets called
bar[i] = BindingSource[index];
i++;
}
}
Basically comparing a string that is entered, and trying to get that position from the array.
If I initialize position to 0 then it returns the position zero of the array, if I initialize to 1 then it gives me the item in slot 1, so it's skipping the compare statement.
I also tried using (custStatus == cardStatus[i])
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
int position= 0;
int discount;
for(int i = 0; i < 2; i++)
{
if (string.Equals(custStatus, cardStatus[i]))
position = i;
}
discount = pDiscount[position];
return discount;
}
With your code, there's no way to tell if position = 0 means custStatus was found in your cardStatus array or if no match was made at all and the default value is being used. I'd recommend either using a boolean matchFound variable or setting position = -1 and adding an extra if statement at the end either way. Either:
boolean matchFound = false;
...
if(matchFound)
{
discount = pDiscount[position];
}
or else
int position = -1;
...
if(position >= 0)
{
discount = pDiscount[position];
}
Give this a try:
public static int discount(string[] cardStatus, int[] pDiscount, string custStatus) {
var position = Array.IndexOf(cardStatus, custStatus);
return (position == -1) ? -1 : pDiscount[position];
}
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
for(int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length); i++)
{
if (string.Equals(custStatus, cardStatus[i]))
{
return pDiscount[i];
}
}
return -1;
}
Don't be afraid to return directly from FOR-loop, it is old-school that teaches to have only one return point from method. You can have as many returns as it helps you to keep your code clean and easy to read.
And perhaps it would be better to use the following expression in for-loop as it will guard you from possible different lengths of arrays:
for (int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length; i++)
This looks ok, even though this is somewhat more straightforward:
for(int i = 0; i < cardStatus.Length; i++)
{
if (custStatus == cardStatus[i])
{
position = i;
break;
}
}
Given your question it appears to be the case that all cardStatus[i] match custStatus - did you check the input?
Also given your code what happens if there is no match? Currently you would return pDiscount[0] - that doesn't seem to be correct.
Hi all i am trying to write and anonymous delegate. as the integer variable is shared among the delegate i need it to be the local instance of every delegate such that rs[0] always gets nics[0], rs[1] always gets nics[1] and so on... how will i achieve this.
for (int i = 0; i < nics.Count; i++)
{
rs[i] = new RollingSeries(monitor, new RollingSeries.NextValueDelegate(delegate()
{
return GetNetworkUtilization(nics[i]);
}));
}
Abdul khaliq
Make a local copy of i:
for (int i = 0; i < nics.Count; i++)
{
int j = i;
rs[i] = new RollingSeries(monitor, new RollingSeries.NextValueDelegate(delegate()
{
return GetNetworkUtilization(nics[j]);
}));
}
The Beauty of Closures
Use a local to get a different value per iteration
for (int i = 0; i < nics.Count; i++)
{
int localI = i;
rs[i] = new RollingSeries(monitor, new RollingSeries.NextValueDelegate(delegate()
{
return GetNetworkUtilization(nics[localI]);
}));
}
Put int j = i inside your loop and refer to j within the lambda expression.
If you are curious about why this happens, here is an MSDN blog entry containing a detailed technical explanation: Closing over the loop variable considered harmful