0

Code example:

using System;

public class Test {

    public static void Main() {
        int a = 0;
        if(a++ == 0){
            Console.WriteLine(a);
        }
    }
}

In this code the Console will write: 1. I can write this code in another way:

public static void Main() {
        int a = 0;
        if(a == 0){
            a++;
            Console.WriteLine(a);
        }
}

These two examples work exactly the same (from what I know about postfix). The problem is with this example coming from the Microsoft tutorials:

using System;

public class Document {

// Class allowing to view the document as an array of words:
public class WordCollection {
    readonly Document document;

    internal WordCollection (Document d){
        document = d;
    }

    // Helper function -- search character array "text", starting
    // at character "begin", for word number "wordCount". Returns
    //false if there are less than wordCount words. Sets "start" and
    //length to the position and length of the word within text
    private bool GetWord(char[] text, int begin, int wordCount,
                         out int start, out int length) {

        int end = text.Length;
        int count = 0;
        int inWord = -1;
        start = length = 0;
        for (int i = begin; i <= end; ++i){
            bool isLetter = i < end && Char.IsLetterOrDigit(text[i]);
            if (inWord >= 0) {
                if (!isLetter) {
                    if (count++ == wordCount) {//PROBLEM IS HERE!!!!!!!!!!!!
                        start = inWord;
                        length = i - inWord;
                        return true;
                    }
                    inWord = -1;
                }
            } else {
                if (isLetter) {
                    inWord = i;
                }
            }
        }
        return false;
    }

    //Indexer to get and set words of the containing document:
    public string this[int index] {
        get 
        {
            int start, length;
            if(GetWord(document.TextArray, 0, index, out start,
                                                     out length)) {
                return new string(document.TextArray, start, length);                                            
            } else {
                throw new IndexOutOfRangeException();
            }
        }
        set {
            int start, length;
            if(GetWord(document.TextArray, 0, index, out start,
                                                      out length))
            {
                //Replace the word at start/length with 
                // the string "value"
                if(length == value.Length){
                    Array.Copy(value.ToCharArray(), 0,
                               document.TextArray, start, length);
                }                   
                else {
                    char[] newText = new char[document.TextArray.Length +
                                              value.Length - length];
                    Array.Copy(document.TextArray, 0, newText, 0, start);
                    Array.Copy(value.ToCharArray(), 0, newText, start, value.Length);
                    Array.Copy(document.TextArray, start + length, newText, 
                               start + value.Length, document.TextArray.Length - start - length);
                    document.TextArray = newText;
                }
            } else {
                throw new IndexOutOfRangeException();
            }
        }
    }

    public int Count {
        get {
            int count = 0, start = 0, length = 0;
            while (GetWord(document.TextArray, start + length,
                    0, out start, out length)) {
                        ++count;
            }
            return count;
        }
    }
}

// Class allowing the document to be viewed like an array
// of character
public class CharacterCollection {

    readonly Document document;

    internal CharacterCollection(Document d) {
        document = d;
    }

    //Indexer to get and set character in the containing
    //document
    public char this[int index] {
        get {
            return document.TextArray[index];
        }
        set {
            document.TextArray[index] = value;
        }
    }

    //get the count of character in the containing document
    public int Count {
        get {
            return document.TextArray.Length;
        }
    }
}

//Because the types of the fields have indexers,
//these fields appear as "indexed properties":
public WordCollection Words;
public readonly CharacterCollection Characters;

private char[] TextArray;

public Document(string initialText) {
    TextArray = initialText.ToCharArray();
    Words = new WordCollection(this);
    Characters = new CharacterCollection(this);
}

public string Text {
    get {
        return new string(TextArray);
    }
}

class Test {
    static void Main() {
        Document d = new Document(
            "peter piper picked a peck of pickled peppers. How many pickled peppers did peter piper pick?"              
        );

        //Change word "peter" to "penelope"
        for(int i = 0; i < d.Words.Count; ++i){
            if (d.Words[i] == "peter") {
                d.Words[i] = "penelope";
            }
        }

        for (int i = 0; i < d.Characters.Count; ++i) {
            if (d.Characters[i] == 'p') {
                d.Characters[i] = 'P';
            }
        }

        Console.WriteLine(d.Text);
    }
}

}

If I change the code marked above to this:

if (count == wordCount) {//PROBLEM IS HERE
                        start = inWord;
                        length = i - inWord;
                        count++;
                        return true;
}

I get an IndexOutOfRangeException, but I don't know why.

AR89
  • 3,548
  • 7
  • 31
  • 46
  • 3
    _Well_, [What is an “index out of range” exception, and how do I fix it?](http://stackoverflow.com/questions/24812679/what-is-an-index-out-of-range-exception-and-how-do-i-fix-it) – Soner Gönül Jan 19 '15 at 14:55
  • 1
    Where exactly is the exception thrown? What are the values of the variable (inside the `[]`) at this point? (use breakpoints, use debugger) – DrKoch Jan 19 '15 at 14:58
  • Try putting your examples in a loop and see what the difference is. – juharr Jan 19 '15 at 15:00
  • The line you've marked as a 'problem' will not thrown an `IndexOutOfRange` exception. Which line is throwing that? – Rufus L Jan 19 '15 at 15:15
  • It's the exception thrown by the get of the WordCollection indexed property. – AR89 Jan 19 '15 at 15:51

4 Answers4

3

In your version of the code, count is only being incremented when count == wordCount; in the Microsoft version, it's being incremented whether the condition is met or not.

adv12
  • 8,443
  • 2
  • 24
  • 48
  • you didn't explain why this causes an exception – Selman Genç Jan 19 '15 at 15:15
  • 1
    True; I assumed, since this was the only functional difference between the working code and the broken code, that it would eventually lead to the `IndexOutOfRangeException` seen by the OP. But you're right that I didn't take the time to trace things all the way through to that exception, which would have made for an even better answer. If you've done the work, by all means add a better answer and earn some rep. (Edit: I see you have added an answer.) – adv12 Jan 19 '15 at 15:22
3

Your initial assumption is incorrect (that the two examples work exactly the same). In the following version, count is incremented regardless of whether or not it is equal to wordCount:

if (count++ == wordCount)
{ 
    // Code omitted
}

In this version, count is ONLY incremented when it is equal to wordCount

if (count == wordCount)
{ 
    // Other code omitted
    count++;
}

EDIT

The reason this is causing you a failure is that, when you are searching for the second word (when wordCount is 1), the variable count will never equal wordCount (because it never gets incremented), and therefore the GetWord method returns false, which then triggers the else clause in your get method, which throws an IndexOutOfRangeException.

Rufus L
  • 36,127
  • 5
  • 30
  • 43
  • @Selman22 Or whoever downvoted, I added the explanation for why this is causing the exception (I thought it was kind of obvious given my original explanation of the error in assumption, but maybe not?). – Rufus L Jan 19 '15 at 18:19
0
using System;

public class Test {

    public static void Main() {
        int a = 0;
        if(a++ == 0){
            Console.WriteLine(a);
        }
    }
}  

Is not quite the same as:

public static void Main() {
    int a = 0;
    if(a == 0){
        a++;
        Console.WriteLine(a);
    }
}

In the second case a++ is executed only if a == 0. In the first case a++ is executed every time we check the condition.

dmigo
  • 2,849
  • 4
  • 41
  • 62
-1

There is your mistake:

public static void Main() {
        int a = 0;
        if(a == 0){
            a++;
            Console.WriteLine(a);
        }
}

It should be like this:

public static void Main() {
        int a = 0;
        if(a == 0){
            a++;
            Console.WriteLine(a);
        }
        else
            a++;
}

a gets alwasy increased. This means, that in your code example count will get only increased when count == wordCount (In which case the method will return true anyway...). You basicly never increasing count.

Alex H
  • 1,424
  • 1
  • 11
  • 25
  • You answer is correct, I don't know why you've been downvoted. I've choosen another answer because it explain also why the exception it thrown. – AR89 Jan 20 '15 at 11:26
  • Thanks a lot. I got one downvote before i was able to edit my answer (the code formating was gone :( ) – Alex H Jan 20 '15 at 11:54