2014-09-29 2 views
1

Это всего лишь языковое любопытство, а не проблема.IEnumerable, .ElementAt и unsigned/signed индексы в C#?

Метод ElementAt() IEnumerable принимает целые числа, чтобы получить N-й элемент перечислимой коллекции.

Например

var list = new List<char>() { 'a', 'b', 'c' }; 
var alias = list.AsEnumerable(); 
int N = 0; 
alias.ElementAt(N); //gets 'a' 

Все хорошо, однако, почему не ElementAt() принимает целые числа без знака (UINT)? , например.

uint N = 0; 
alias.ElementAt(N); //doesn't compile 

Я могу понять, почему ElementAt может принимать целые числа, чтобы отрицательные индексы (например, Python позволяет отрицательные индексы, где список [-1] ссылается на последний элемент), так что имеет смысл иметь принимать отрицательные индексы для этих языков которые действительно используют их, даже если C# нет.

Но я не могу понять аргументы в пользу запрета целых чисел без знака, если что-то целое число без знака лучше, поскольку оно гарантирует, что индекс не будет отрицательным (так что только верхняя граница диапазона должна быть проверена).

Лучшая вещь, о которой я мог думать, - это, возможно, команда CLR решила стандартизировать знаковые целые числа, чтобы разрешить другим языкам (например, Python), которые имеют отрицательные индексы, использовать один и тот же код и обеспечивать соответствие диапазонов между языками.

У кого-нибудь есть лучшее/авторитетное объяснение того, почему .ElementAt() не допускает неподписанные ints?

-Marcin

+3

беззнаковых целых не [CLS совместимый] (http://msdn.microsoft.com/en-us/library/12a7a7h3%28v=vs 0,110% 29.aspx). –

+0

Спасибо. Открыл глаза на соответствие CLS. http://stackoverflow.com/questions/6325/why-are-unsigned-ints-not-cls-compliant может быть полезен и всем, кто интересуется всем этим. – Marcin

ответ

1

Реальная причина заключается в том, что .NET массивы могут быть отличны от нуля на основе, даже если язык С # не поддерживает декларирование таких массивов. Их можно создать, используя Array.CreateInstance Method (Type, Int32[], Int32[]). Обратите внимание на специальное имя типа созданного объекта (System.Int32 [*]) со звездочкой в ​​нем.

Список реализован с использованием массива внутри, и было бы нецелесообразно использовать другой тип для индексирования.

Кроме того, свойство Count обычно участвует в вычислении индекса массива, в котором частичный результат может быть отрицательным. Смешивание типов в выражении было бы громоздким и подверженным ошибкам.

Наличие типа, который не может представлять отрицательный индекс, не помогло бы в обнаружении ошибок. Использование автоматического обрезания с операцией unchecked не приведет к исправлению ошибок вычисления индекса логического массива в приложении.

Следующий пример показывает отрицательное на основе массива манипуляции C#:

var negativeBasedArray = Array.CreateInstance(typeof(Int32), 
    new []{2}, // array of array sizes for each dimension 
    new []{-1}); // array of lower bounds for each dimension 
Console.WriteLine(negativeBasedArray.GetType()); // System.Int32[*] 
negativeBasedArray.SetValue(123, -1); 
negativeBasedArray.SetValue(456, 0); 
foreach(var i in negativeBasedArray) 
{ 
    Console.WriteLine(i); 
} 
// 123 
// 456 
Console.WriteLine(negativeBasedArray.GetLowerBound(0)); // -1 
Console.WriteLine(negativeBasedArray.GetUpperBound(0)); // 0 
Смежные вопросы