Directory Freebies VS CheatSheet Forum

RSS

Email

Translate

Home About Archive Privacy Contact Advertise Write for Dev102
Posted by moshe on Jul 28th, 2009 | Filed under .Net, C# |

Last week, I stumbled upon the following piece of code:

 

IList<double> doubles = new List<double> {22.123, 400.12, 100.22};
foreach (int number in doubles)
{
    Console.WriteLine("The Current Number Is : {0}", number);
}

Can you see the bug in that code? We convert all of the doubles in the list to integers, truncating them. I was very surprised that the compiler didn’t warn me about this issue, especially because the compiler would not let me write this code:

 

double someDouble = 22.523;
int someInt = someDouble;

An explicit conversion is necessary here:

 

int someInt = (int)someDouble;

What is the difference between those two cases? Can’t I expect a uniform behavior from the compiler? The reason is probably historic - before C# 2.0 which introduced us with Generics, all of the containers held their items as objects. If the foreach statement didn’t automatically do the conversion, the user would have to explicitly cast every item in the collection from object

 

 

ArrayList array = new ArrayList {"moshe", "levi"};
foreach (object obj in array)
{
    string str = obj as string;
    if (str != null)
       Console.WriteLine("The Current element is {0}", str);
}

In most cases, the collection items are of the same type so in order to reduce the explicit conversion effort, the C# developers decided to do an automatic conversion for us. If we test the MSIL which is generated for the foreach statement, we can clearly notice to the “injected” code which is responsible for the conversion:

 

clip_image002

Now that we understand what happens, here is a way to avoid those kinds of bugs. Using the var keyword, we can ask the compiler to define the type of the collection item according to its value. Here it is:

IList<double> doubles = new List<double> {22.123, 400.12, 100.22};
foreach (var number in doubles)
{
    Console.WriteLine("The Current Number Is : {0}", number);
}

By changing this code, the compiler is responsible for determining the type of “number”. In most cases, that is exactly what we want…

Tags: , , , , , , ,

6 Responses to “Pay Attention to the Foreach Implicit Casting”


  1. Frank Quednau Said on Jul 28, 2009 :

    In cases where some type provides you only with a non-generic IEnumerable you will be provided with object as the var type. THat may not be what you want. The implicit casting is a remnant of 1.1 days, I don’t think it would be too necessary right now, alas, the non-generic interfaces are still around.

  2. Frank Quednau Said on Jul 28, 2009 :

    Forget my comment…

  3. Oisin G. Said on Jul 29, 2009 :

    bwt, when you say “an implicit conversion is needed here”, you really mean an explicit one…

  4. Josh Said on Aug 4, 2009 :

    Sob, I didn’t see the problem. You’ve really taken a solid look at the whole casting situation here. Thx for making your results available.

  5. Arun Said on Dec 29, 2010 :

    Im using this code
    when i m search the MailItem if it got the Mailmeeting and calender then it break the code not read the mailitem please help me
    Outlook.Application oOutlook;
    Outlook.NameSpace oNs;
    Outlook.MAPIFolder oFldr;
    long iAttachCnt;
    oOutlook = new Outlook.Application();
    oNs = oOutlook.GetNamespace(”MAPI”);
    oFldr = oNs.PickFolder();
    foreach (Outlook.MailItem oMessage in oFldr.Items)
    {
    iAttachCnt = oMessage.Attachments.Count;
    if (iAttachCnt > 0)
    {
    for (int i = 1; i <= iAttachCnt; i++)
    {
    string FileNameExt = oMessage.Attachments[i].FileName;
    FileNameExt = Path.GetExtension(FileNameExt);
    if (FileNameExt == “.docx” || FileNameExt == “.doc”)
    {
    StringBuilder str = new StringBuilder();
    StringBuilder strBody = new StringBuilder();
    str.Append(oMessage.SenderName.ToString() + “,”);
    if (oMessage.Subject != null)
    {
    str.Append(oMessage.Subject.ToString() + “,”);
    }
    else
    {
    str.Append(string.Empty + “,”);
    }
    str.Append(oMessage.SentOn.ToShortDateString() + “,”);
    try
    {
    if (oMessage.Body != null)
    {
    strBody.Append(oMessage.Body.ToString());
    }
    else
    {
    strBody.Append(string.Empty);
    }
    }
    catch { }
    str.Append(oMessage.SenderEmailAddress.ToString() + “,”);
    str.Append(i.ToString() + “,” + oMessage.Attachments[i].FileName + “,”);
    str.Append(oMessage.To.ToString() + “,”);

    string TextString = str.ToString();
    string[] NewText = TextString.Split(’,');
    {
    string SenderName = NewText[0].ToString();
    string Subject = NewText[1].ToString();
    string SentOn = NewText[2].ToString();
    string Body = strBody.ToString();
    string SenderEmailId = NewText[3].ToString();
    string Attatchment = NewText[5].ToString();
    string Tomail =NewText[6].ToString();
    SaveInformation(SenderName, Subject, SentOn, Body, SenderEmailId, Attatchment,Tomail);
    }
    string AttatchmentSave = oMessage.Attachments[i].FileName;
    oMessage.Attachments[i].SaveAsFile(”C:\\Users\\abc\\Desktop\\Attatchment\\” + AttatchmentSave);
    }
    else
    {

    }
    }
    }
    }

1 Trackback(s)

  1. Jul 29, 2009: Reflective Perspective - Chris Alcock » The Morning Brew #400

Post a Comment

Write Article for Dev102

Write for Dev102!

We pay for user submitted tutorials and articles that we publish. Anyone can send in a contribution

Learn More