음수가 될 수없는 값에 대해 C #에서 uint를 사용해야합니까?


80

uint대신 수많은 길이 / 개수 속성 등이있는 클래스를 구현해 보았습니다 int. 그러나 그렇게하는 동안 아무도 그렇게하고 싶어하지 않는 것처럼 그렇게하는 것이 실제로 고통 스럽다는 것을 깨달았습니다.

정수 유형을 전달하는 거의 모든 것이를 반환 int하므로 여러 지점에서 캐스트가 필요합니다. StringBuffer버퍼 길이가 해당 클래스의 필드 중 하나에 기본 설정되어있는를 생성하고 싶었습니다 . 캐스트도 필요합니다.

그래서 int여기로 돌아 가야할지 궁금 했습니다. 어쨌든 전체 범위를 사용하지는 않습니다. 나는 단지 내가 처리하고있는 것이 단순히 부정적 일 수 없기 때문에 (만약 있다면 그것은 오류 일 것이다) 실제로 사용하는 것이 좋은 생각이라고 생각했다 uint.

추신 : 나는 이 질문을 보았고 이것은 적어도 프레임 워크 자체가 항상 사용하는 이유를 설명 int하지만, 심지어 자체 코드에서도 실제로 그것이 실제로 uint원하지 않는다고 생각하게 만드는 것이 실제로 번거 롭습니다 .


답변:


42

uint음이 아닌 정수를 포함하는 변수를 엄격하게 사용해야하지만 항상 실행 가능하지 않은 이유 중 하나를 발견했습니다.

이 경우 캐스트를해야하는 가독성의 감소는 그만한 가치가 없다고 생각합니다.


2
말하기 어렵습니다. 캐스트가 인덱서의 가독성을 많이 감소시키고 래퍼를 만들 수 있다고 생각하지 않습니다. 음수가되는 정수는 고통스럽고 값 비싼 버그입니다.
user1496062

6
int에 대한 래퍼를 만들어야한다면 가독성 문제 이상이 있습니다. :)
S ..

61

다른 답변에 uint를 공용 필드, 속성, 메서드, 매개 변수 등의 유형으로 사용하는 것은 공용 언어 사양 규칙을 위반하는 것이며 가능하면 피해야한다는 것을 추가 할 것입니다.


3
그리고 나는 그것을 엄격히 따르는 마이크로 소프트에 의해 화상을 입었습니다. IntPtr에는 uint 생성자가 있어야합니다.
Joshua

3
또한 자연수를 지원하는 경우 추가 할 것입니다. 예를 들어이 유형이 0에서 6까지의 값이면 모든 배열 경계 검사를 제거 할 수 있으므로 성능이 5-10 % 크게 향상됩니다.
user1496062

위의 진술에 동의하십니까, 리퍼 트 ​​씨?
AgentFire

@AgentFire :이 성명서는 누군가가 무언가를했다면 특정 성능 향상을 가져올 것이라고 주장합니다. 나는 반사 실적 주장을 평가할 능력이 없습니다. 그 주장이 사실인지 알고 싶다면, 사용자에게 내가 아니라 그들의 주장을 정당화하는 것이 무엇인지 물어보십시오. 나는 뒷받침되지 않는 주장을하는 사람이 아닙니다.
Eric Lippert

1
당신의 짧은 긴 "난 몰라"의 중 하나 @EricLippert는 그것을 밤은 : P
AgentFire

4

음수 값은 종종 오류 상태를 알리는 데 사용되며 연산의 크기는 종종 함수 호출에 의해 반환됩니다. 따라서 음수 값은 예외 메커니즘에 의존하지 않고 오류를 나타낼 수 있습니다.

또한 .NET은 종종 직접적인 C 라이브러리를 기반으로 빌드되므로이 규칙을 계속하는 것이 좋습니다. 더 큰 인덱스 공간이 필요한 경우 다른 오류 신호 메커니즘에 대한 규칙을 위반할 수 있습니다.


24
.NET은 오류 코드를 반환하는 것보다 예외를 던지는 것과 상당히 일치합니다. -1 반환은 관리 코드에서 흔히 볼 수있는 것이 아닙니다.
ChrisV

동의했지만 Windows 기술 전반에 걸쳐 널리 퍼져있는 디자인 규칙에 대해 이야기하고 있습니다 (지원되는 예외 외에도)-저수준 코드와 인터페이스하는 .NET 라이브러리 부분은 CRT 오류 코드와 예외간에 변환해야합니다. -그것은 그들이 uint가 아닌 int의 관습을 가져 오는 이유를 이해할 수 있습니다.
Hassan Syed

@HassanSyed는 여전히 일부 winapi가 음수 값을 반환하면 프레임 워크는 여전히 자체 예외를 발생시켜 모든 것을 깔끔한 쉘로 래핑하므로 여기에 인수가 적용되지 않습니다.
AgentFire

3

내 개인적인 느낌은 아마도 int에 충실해야한다는 것입니다. .NET이 어쨌든 사용할 수 없을 것 같은 숫자 범위를 되찾기 위해 거의 모든 단일 속성 액세스에 캐스트를 추가 할 가치가 없습니다.


3

int를 사용하면 연산에서 정수 오버플로를 감지하는데도 도움이됩니다.


너무 넘쳐서 0에 도달하면 100 % 정확하지 않습니다. 다시 말하지만, 기본적으로 오버 플로우 방지가 활성화되어 있습니다.
AgentFire

3

IMO, 사용의 단점은 uint오류 조건을 모호하게한다는 것입니다. 다음 코드와 동일한 것은 좋지 않습니다.

if (len < 0)
    terminate_program("length attained impossible value.");

물론 여러분의 프로그램은 처음부터 어떤 것도 잘못 계산해서는 안되지만 전파없이 수치 오류를 빠르게 감지하도록 작성해야한다고 생각합니다. MaxValue가 2 ^ 31이면 충분할 경우, 위에서 예시 한대로 int적절한 사용 System.Diagnostics.Debug.Assert()및 해당 오류 검사 와 함께 사용 합니다.

당신이 경우에 사용 uint와 함께 사용 checked언더 플로우 방지와 같은 결과를 얻을 수 있습니다. 그러나 어떤 목적으로 캐스트를 사용하는 기존 코드에 검사를 적용하는 것이 약간 어렵다는 것을 알았습니다.


2

필요하지 않다면 상류에서 수영하지 마십시오. 캐스트로 코드를 작성하지 않으면 코드가 더 읽기 쉬워집니다. 또한 가능한 값이 int에 맞으면 int를 사용하는 것은 문제가되지 않습니다.

만약 당신이 int를 넘칠 까봐 두렵다면, 꼭 거기에 ..하지만 너무 일찍 최적화하지 마세요.

나는 캐스트 최소화의 향상된 가독성이 int를 사용하는 버그의 약간 높아진 위험보다 큽니다.


2

값이 양수인지 확인하려면 assert를 사용하는 것이 더 좋은 방법 일 것입니다 (이것은 단지 디버깅 기술 일 뿐이며 최종 코드에서는 절대 발생하지 않도록해야합니다).

using System.Diagnostics;
...
Debug.Assert (i > 0);

1
를 참조하십시오 ArgumentOutOfRangeException.
Fred
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.