Perché il metodo Count () usa la parola chiave "controllata"?


23

Mentre cercavo la differenza tra Count e Count () , ho pensato di dare un'occhiata al codice sorgente di Count(). Ho visto il seguente frammento di codice in cui mi chiedo perché la checkedparola chiave sia necessaria / necessaria:

int num = 0;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        num = checked(num + 1);
    }
    return num;
}

Il codice sorgente:

// System.Linq.Enumerable
using System.Collections;
using System.Collections.Generic;

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
    }
    ICollection<TSource> collection = source as ICollection<TSource>;
    if (collection != null)
    {
        return collection.Count;
    }
    IIListProvider<TSource> iIListProvider = source as IIListProvider<TSource>;
    if (iIListProvider != null)
    {
        return iIListProvider.GetCount(onlyIfCheap: false);
    }
    ICollection collection2 = source as ICollection;
    if (collection2 != null)
    {
        return collection2.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num = checked(num + 1);
        }
        return num;
    }
}

2
.NET 4.0 non aveva ancora questo controllo, 4.5. Rende in qualche modo probabile che ciò sia stato fatto per evitare problemi con gli iteratori WinRT , si noti che usano uint.
Hans Passant,

Risposte:


35

Perché non vuole restituire un numero negativo nell'evento (certamente improbabile) che ci siano più di 2 miliardi di articoli dispari nella sequenza - o un numero non negativo ma solo sbagliato nel caso (anche più improbabile) che ci sono più di 4 miliardi di oggetti dispari nella sequenza. checkedrileverà la condizione di overflow.


1
Per impostazione predefinita, @ DavidMårtensson C # unchecked; può essere sfogliato di checkeddefault a livello globale tramite uno switch del compilatore, ma francamente lo vedo raramente usato, quindi penso che sia sbagliato suggerire che C # sia "normalmente" eseguito in checkedmodalità; nota anche che unsafenon ha alcuna interazione conunchecked
Marc Gravell

1
Questa è stata una novità per me, l'ho testato in un progetto prima di scrivere e C # si è lamentato dell'overflow fino a quando non l'ho aggiunto senza controllarlo? Modifica: ho trovato la risposta a ciò che ho visto "Per le espressioni costanti (espressioni che possono essere valutate completamente in fase di compilazione), viene sempre verificato il contesto predefinito. A meno che un'espressione costante non sia esplicitamente inserita in un contesto non controllato, gli overflow che si verificano durante la compilazione la valutazione in tempo dell'espressione causa errori in fase di compilazione. "
David Mårtensson,

@ DavidMårtensson ah, sì - buona sfumatura; Stavo parlando di runtime; come dici tu: il tempo di compilazione è diverso
Marc Gravell

Ma il tempo di compilazione non si applica all'esempio del post, quindi il mio commento era errato e l'ho eliminato.
David Mårtensson,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.