Защо Stream.Write не приема UInt?

Струва ми се изключително нелогично, че Stream.Write използва int, вместо UInt... Има ли обяснение, различно от "наследен" код за този факт? Някой би ли искал да напише -1 байта?!?


person Leonardo    schedule 01.06.2015    source източник


Отговори (3)


Неподписаните типове не са съвместими с CLS, следователно Stream.Write не използва uint за отместване и броене.

Вижте: uint (справочник за C#)

Типът uint не е CLS-съвместим. Използвайте int, когато е възможно.

Има стара статия: Защо нямаме неподписани типове в CLS от Брад Ейбрамс (2 септември 2003), който обяснява причината:

Има обаче един проблем, който продължава да възниква: Защо не разрешихме неподписани типове (UInt32 и други подобни) в CLS?

Е, наистина има два отговора на този въпрос. На първо ниво някои езици (като VB.NET) не предлагат пълна поддръжка за неподписани типове. Например не можете да имате неподписани литерали във VB.NET…. Но за да бъда честен, това не е напълно задоволителен отговор, защото когато стартирахме CLS, вие също не можехте да създавате подкласове във VB.NET, но разширихме този език, за да поддържаме това, което знаехме, че хората биха искали. Можехме да направим същото нещо с неподписани типове. Но ние не го направихме. Защо не? Е, това има по-дълбока причина. Всъщност същата причина, поради която ранните бета версии на езика C# не поддържаха неподписани типове (без ushort, uint и други подобни).

Общото усещане сред много от нас е, чепо-голямата част от програмирането се извършва със подписани типове. Всеки път, когато превключите към неподписани типове, вие принуждавате умствено превключване на модела (и грозен каст). При най-лошия каст изграждате цял паралелен свят от API, които приемат неподписани типове. Стойността на избягването на проверката „‹ 0“ не си заслужава включването на генерични продукти в CLS.

(Имайте предвид, че по-новата версия на VB.Net (VB 8 и нагоре) поддържа неподписани типове).

Още нещо (вероятно несвързано) за добавяне, Stream.Write внедряване има проверки за отрицателни стойности:

[System.Security.SecuritySafeCritical]  // auto-generated
public override void Write(byte[] array, int offset, int count) {
    if (array==null)
        throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
    if (offset < 0)
        throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
    if (count < 0)
        throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
    if (array.Length - offset < count)
        throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
person Habib    schedule 01.06.2015

От uint MSDN само

Типът uint не е CLS-съвместим. Използвайте int, когато е възможно.

Така че Stream.Write използва int за отместване и броене.

Причините, дадени от ShuggyCoUk го правят още ясно:

  • uint не е съвместим с CLS, поради което правенето на вграден тип (масив) зависим от него би било проблематично
  • The runtime as originally designed prohibits any object on the heap occupying more than 2GB of memory. Since the maximum sized array that would less than or equal to this limit would be new byte[int.MaxValue] it would be puzzling to people to be able to generate positive but illegal array lengths.
  • Исторически C# наследява голяма част от своя синтаксис и конвенция от C и C++. В тези масиви са просто аритметични указатели, така че отрицателното индексиране на масиви е възможно (въпреки че обикновено е незаконно и опасно). Тъй като голяма част от съществуващия код предполага, че индексът на масива е отрицателен, това би било фактор
  • Във връзка с това използването на цели числа със знак за индекси на масиви в C/C++ означава, че взаимодействието с тези езици и неуправляваните функции така или иначе ще изисква използването на int при тези обстоятелства, което може да обърка поради несъответствието.
  • Реализацията на BinarySearch (много полезен компонент на много алгоритми) разчита на възможността да използва отрицателния диапазон на int, за да покаже, че стойността не е намерена и мястото, където трябва да бъде вмъкната такава стойност за поддържане на сортирането.
  • Когато работите с масив, е вероятно да искате да вземете отрицателно отместване на съществуващ индекс. Ако сте използвали отместване, което би ви отвело след началото на масива, използвайки единица, тогава поведението на обвиване би направило вашия индекс вероятно легален (в това, че е положителен). С int резултатът би бил незаконен (но безопасен, тъй като времето за изпълнение ще предпази от четене на невалидна памет)
person Rahul Tripathi    schedule 01.06.2015

Вярвате или не, целите числа без знак не са част от спецификацията на общия език (CLS).

Запис в MSDN за uint:

Типът uint не е CLS-съвместим. Използвайте int, когато е възможно.

Така Microsoft използва int тук вместо uint в интерес на съответствието с CLS.

person Stephen Kennedy    schedule 01.06.2015