상수를 사용하는 것이 올바른 상황입니까?


42

그래서 교수님은 제가 진행하고있는 프로젝트에 대한 피드백을 제공하고있었습니다. 그는이 코드에 몇 가지 마크를 도킹했습니다.

if (comboVendor.SelectedIndex == 0) {
  createVendor cv = new createVendor();
  cv.ShowDialog();
  loadVendors();
}

콤보 박스 "인덱스 변경"핸들러에 있습니다. 사용자가 새 공급 업체를 만들려고 할 때 사용되는 최상위 옵션 (인덱스 0, 변경되지 않음)은 "새 공급 업체 생성"대화 상자를 엽니 다. 따라서 내 콤보 상자의 내용은 다음과 같습니다.

Create New Vendor...
Existing Vendor
Existing Vendor 2
Existing Vendor 3

그의 문제는 첫 번째 라인 코드입니다.

if (comboVendor.SelectedIndex == 0)

그는 0이 일정해야한다고 주장하고 실제로 그로 인해 마크를 도킹했습니다. 그는 코드에서 리터럴을 전혀 사용해서는 안된다고 주장합니다.

문제는 그 상황에서 해당 코드를 상수로 만들고 싶은 이유를 이해하지 못한다는 것입니다. 그 지수는 절대 바뀌지 않으며 조정해야 할 것이 아닙니다. 매우 구체적인 상황에 사용되며 절대 변경되지 않는 메모리에 단일 0을 유지하는 것은 메모리 낭비처럼 보입니다.


32
그는 독단적입니다. 매직 넘버는 일반적으로 피하는 것이 좋습니다. -1, 0 및 1은 해당 규칙의 예외로 간주 될 수 있다고 생각합니다. 또한,이 같은 일정은 문자 0보다 더 많은 공간받지 않을 것
데이브 무니

23
@DaveMooney : 여기에 무릎이 부딪치지 않습니까? " contains " -1str.indexOf(substr) != -1대한 것과 같은 것들이 일반적으로 정당화 되는 것은 사실입니다 . 그러나 여기서 0의 의미는 명백하지 않으며 (새로운 공급 업체를 만드는 것과 어떤 관계가 있지 않습니까?) 정확하지도 않습니다 (새로운 공급 업체를 만드는 방법이 바뀌면 어떻게 되나요?). strsubstr

62
규칙을 어기려면 규칙을 배워야합니다
Ryathal

12
이 방법이 예기치 않게 실패했습니다. 목록은 알파벳순으로 정렬되었습니다. 내가 사용 - 새로 만들기 - - - 대시 정렬 제 하드 CreateNew 방법에 인덱스 0을 코딩 할 수 있도록. 그런 다음 누군가 대시 앞에 정렬 하는 작은 따옴표 'My Item'으로 시작하는 항목을 추가했습니다 . 다음에 목록을로드 할 때 하드 코딩으로 인해 프로그램이 중단되었습니다. 고객의 데이터를 복구하기 위해 목록의 데이터 파일을 수동으로 수정해야했습니다.
Hand-E-Food

14
int.Zero대신 그를 행복하게 만들 수 있습니다 :)
Paul Stovell

답변:


90

C #에서이를 수행하는 실제 올바른 방법은 ComboItems의 순서에 전혀 의존하지 않는 것 입니다.

public partial class MyForm : Form
{
    private readonly object VENDOR_NEW = new object();

    public MyForm()
    {
        InitializeComponents();
        comboVendor.Items.Insert(0, VENDOR_NEW);
    }

    private void comboVendor_Format(object sender, ListControlConvertEventArgs e)
    {
        e.Value = (e.ListItem == VENDOR_NEW ? "Create New Vendor" : e.ListItem);
    }

    private void comboVendor_SelectedIndexChanged(object sender, EventArgs e)
    {
        if(comboVendor.SelectedItem == VENDOR_NEW)
        {
            //Special logic for selecting "create new vendor"
        }
        else
        {
            //Usual logic
        }
    }
}

22
글쎄, 이것이 C #이면 상수에 ALL_CAPS를 사용해서는 안됩니다. 상수는 PascalCased 여야합니다.- stackoverflow.com
questions

4
@ Groky : 왜 중요한가? 상수의 이름을 어떻게 지정해야합니까? 상수에 일관된 방식으로 ALL_CAPS를 사용하면 100 % 정확합니다.
marco-fiset

4
@marcof : 상수가 공용 인터페이스의 일부인 경우 MS 명명 지침을 따라야합니다. 그렇지 않다면, 그는 적어도 모범 사례를 조기에 배워야합니다.
Groky

2
이것은 여전히 ​​올바르지 않습니다. 정수 리터럴 (0)이있는 문자열 리터럴 (새 벤더 작성)로 문제점을 이동시킵니다. 기껏해야 문제는 이제 '색인이 변경되는 경우'대신 '라벨이 변경되는 경우'입니다.
Freiheit

7
@Freiheit : 잘못되었습니다. 여기서 문자열 상수는 표시 전용입니다. 프로그램의 논리에는 영향을 미치지 않습니다. 프로그램 상태를 저장하기 위해 매직-값 / 문자열을 사용하는 것과 달리,이 문자열을 변경 하거나 목록에서 항목을 추가 / 제거하면 아무 것도 깨지지 않습니다.
BlueRaja-대니 Pflughoeft

83

콤보 상자의 순서가 변경 될 수 있습니다. "새 벤더 만들기 ..."앞에 "특별 공급 업체 만들기 ..."와 같은 다른 옵션을 추가하면 어떻게됩니까?

상수를 사용하는 이점은 콤보 상자의 순서에 따라 많은 메서드가있는 경우 상수가 변경되면 모든 메서드가 아니라 상수 만 변경하면된다는 것입니다.

상수를 사용하는 것도 리터럴보다 읽기 쉽습니다.

if (comboVendor.SelectedIndex == NewVendorIndex)

대부분의 컴파일 된 언어는 컴파일 타임에 상수를 대체하므로 성능 저하가 없습니다.


5
변경 할 수있는 색인에 의존하기보다는 value 속성에 설명 코드를 사용합니다 (작성 옵션을 목록 맨 아래로 이동하면 상수 메소드가 절대적으로 중단됩니다). 그런 다음 해당 코드를 찾으십시오.
CaffGeek

1
@Chad 나는 GUI에서 명령으로 컨트롤을 식별하는 것이 매우 취약하다는 데 동의합니다. 언어가 gui 요소에 조회 할 수있는 값 추가를 지원하는 경우이를 사용합니다.
Michael Krussel

3
@solution은 이것이 관례이기 때문에.
Ikke

3
@Ikke 그것은 컨벤션이 아닙니다. stackoverflow.com/questions/242534/…
SolutionYogi

1
C #에 대해 이야기하고 있다면 NewVendorIndex가 관습입니다. 나머지 .NET 스타일과 일치합니다.
MaR December

36

당신이 묘사하는이 상황은 판단 요청이며, 개인적으로 한 번만 사용하고 이미 읽을 수 있다면 개인적으로는 사용하지 않을 것입니다.

진짜 대답은 그가 당신에게 교훈을 가르치기 위해 이것을 골랐다는 것입니다.

그가 교수라는 것을 잊지 마십시오. 그의 일은 코딩과 모범 사례를 가르치는 것입니다.

나는 그가 실제로 꽤 잘하고 있다고 말하고 싶습니다.

그가 조금 절대적으로 벗어날 수도 있지만 마법 번호를 사용하기 전에 다시 생각할 것이라고 확신합니다.

또한이 상황에서 모범 사례로 간주되는 것을 찾기 위해 프로그래머에 대해 온라인 커뮤니티에 참여할 수있을 정도로 귀하의 피부 아래에있었습니다.

교수님의 의견


이 경우 평균이 최종 결과를 정당화 함을 나타내는 +1
oliver-clare

@ Thanos- " 그는 교수임을 잊지 마십시오. 그의 일은 코딩과 모범 사례를 가르치는 것입니다. "이것은 내 교수에게는 해당되지 않았습니다. 그의 임무는 코스가 만들어지면 부서가 느끼는 것이 중요하다는 것을 가르치는 것입니다.
Ramhound

13

[...] 최상위 옵션 (인덱스 0, 절대 변경되지 않음)은 "새 공급 업체 생성"대화창을 엽니 다.

설명해야했던 사실은 상수를 사용해야하는 이유를 증명합니다. 와 같은 상수를 도입하면 NEW_VENDOR_DIALOG코드가 더 자명합니다. 또한, 컴파일러는 상수를 최적화하므로 성능에는 변화가 없습니다.

컴파일러가 아닌 프로그래머를위한 프로그램을 작성하십시오. 마이크로 최적화를 구체적으로 시도하지 않는 한, 그것은 당신처럼 보이지 않습니다.


2
성능을 언급하는 경우에도 -1입니다. 컴퓨터가 최적화되지 않더라도 사용자가 알기 전에 이와 같은 수십억 작업을 수행 할 수 있습니다.
Boris Yankov

3
@Boris OP는 리소스 낭비에 대해 우려하는 것처럼 보였으므로 언급했습니다. 그로 인해 내 대답의 정확성이 어떻게 떨어지는 지 알 수 없습니다.
kba

12

그는 0이 일정해야한다고 주장하고 실제로 그로 인해 마크를 도킹했습니다.

동의합니다. 여기서 0을 사용하는 것은 "마법"입니다. 이 코드를 처음 읽는다고 상상해보십시오. 왜 0이 특별한 지 알지 못하고 리터럴은 0이 특별한 이유에 대해 아무 것도 알려주지 않습니다. 대신에 당신이 말했다 if(comboVendor.SelectedIndex == CreateNewVendorIndex)면 코드가 의미하는 것이 처음 독자에게 매우 분명해집니다.

그는 코드에서 리터럴을 전혀 사용해서는 안된다고 주장합니다.

그것은 극단적 인 입장입니다. 현실적인 위치는 리터럴 사용이 코드가 명확하지 않을 수 있음을 나타내는 빨간색 플래그라고 말할 수 있습니다. 때로는 적절합니다.

문제는 그 상황에서 해당 코드를 상수로 만들고 싶은 이유를 이해하지 못한다는 것입니다. 그 지수는 절대 변하지 않을 것입니다

그것이 결코 변하지 않을 것이라는 것이 그것을 일정하게 만드는 훌륭한 이유 입니다. 이것이 상수를 상수라고하는 이유입니다. 그들은 결코 변하지 않기 때문입니다.

또한 조정해야 할 것이 아닙니다.

정말? 당신이 볼 수 있는 사람이 콤보 상자에 사물의 순서를 변경할 수 있습니다있는 상황을?

미래에 이것이 변경 될 수있는 이유를 알 수 있다는 사실은 그것이 일정 하지 않게 하는 좋은 이유 입니다. 오히려 상수가 아닌 읽기 전용 정적 정수 필드 여야합니다. 상수는 동일하게 유지 보장되는 수량해야합니다 모든 시간을 . Pi와 금의 원자 수는 좋은 상수입니다. 버전 번호는 없습니다. 그들은 모든 버전을 바꿉니다. 금의 가격은 분명히 끔찍한 상수입니다. 매 초마다 바뀝니다. 결코 변하지 않는 일정한 것을 만드십시오 .

매우 구체적인 상황에 사용되며 절대 변경되지 않는 메모리에 단일 0을 유지하는 것은 메모리 낭비처럼 보입니다.

이제 우리는 문제의 핵심에 왔습니다.

이것은 아마도 (1) ​​메모리 및 (2) 최적화에 대한 깊은 결함이 있음을 나타 내기 때문에 아마도 가장 중요한 질문 일 것입니다. 당신은 학교에서 배우고 있으며, 이제 기초에 대한 올바른 이해를 얻을 수있는 좋은 시간입니다. 왜 "0을 메모리에 유지하는 것은 메모리 낭비"라고 믿는 이유를 자세히 설명 할 수 있습니까? 우선, 최소 20 억 바이트의 사용자 주소 지정 스토리지가있는 프로세스에서 4 바이트 메모리 사용을 최적화하는 것이 적절하다고 생각하는 이유는 무엇입니까? 둘째, 정확히 어떤 자원이 여기에서 소비되고 있다고 생각 하십니까? "메모리"가 소비된다는 것은 무엇을 의미합니까?

이러한 질문에 대한 답변은 먼저 최적화 및 메모리 관리에 대한 이해가 어떻게 틀린지 배울 수있는 기회이기 때문에 관심이 있으며, 둘째는 초보자가 왜 기괴한 것을 믿는지 알고 싶어서 설계 할 수 있기 때문입니다. 올바른 신념을 갖도록하는 더 나은 도구.


6

그가 맞아. 네가 옳아. 네가 틀렸어.

그는 개념적으로 매직 넘버를 피해야한다는 것이 맞습니다. 상수는 숫자의 의미에 컨텍스트를 추가하여 코드를 더 읽기 쉽게 만듭니다. 나중에 누군가가 코드를 읽을 때 특정 숫자가 사용 된 이유를 알게됩니다. 그리고 줄 아래로 값을 변경해야하는 경우 특정 숫자가 사용되는 모든 곳을 찾아 보는 것보다 한 곳에서 변경하는 것이 훨씬 좋습니다.

그렇습니다, 당신 말이 맞아요. 이 특정 경우에는 상수가 보장된다고 생각하지 않습니다. 목록에서 첫 번째 항목을 찾고 있는데 항상 0입니다. 절대 23이되지 않습니다. 또는 -pi. 구체적으로 0을 찾고 있습니다. 나는 코드를 일정하게 만들어서 혼란스럽게해야한다고 생각하지 않습니다.

그러나 상수가 변수를 '메모리 사용'으로 전달한다고 가정하면 잘못되었습니다. 인간과 컴파일러에는 상수가 있습니다. 그것은 컴파일러가 컴파일 도중 그 자리에 그 값을 넣도록 지시합니다. 그렇지 않으면 리터럴 숫자를 넣었을 것입니다. 그리고 가장 까다로운 응용 분야를 제외하고 메모리에 상수를 전달하더라도 효율성 손실은 측정 할 수 없습니다. 단일 정수의 메모리 사용에 대한 걱정은 확실히 '조기 최적화'에 해당합니다.


1
세 번째 단락이 아닌 경우 리터럴 0을 사용하는 것이 충분하고 상수가 보장되지 않는다고 주장 하면서이 답변에 거의 투표했습니다. 훨씬 더 나은 해결책은 콤보 상자 항목의 색인 작성에 의존하지 않고 선택한 항목 의 에 의존하는 것이 었습니다 . 매직 상수는 0 또는 3.14이거나 그렇지 않은 경우에도 매직 상수이며 코드를 더 읽기 쉽도록 적절하게 이름을 지정합니다.
Roland Tepp

목록의 값을 사용하는 것이 더 나을 수도 있지만 그의 질문에 관한 것이 아닙니다. 그의 질문은 그것이 상수에 대한 적절한 사용인지에 관한 것이 었습니다. 그리고 GUI와 인터페이스하는 맥락에서 0과 비교하는 경우 (어떤 이유로 든 누군가가 가치에 관계없이 주먹 항목을 찾고있을 것입니다), 그 자리에서 상수를 사용하는 것이 불필요하다고 생각합니다.
GrandmasterB

나는 동의하지 않을 것입니다 ... 코드를 보는 것만으로 0의 의미가 무엇인지 즉시 분명하지 않습니다. 그는 항상 목록에서 첫 번째 항목을 찾고 있다는 것입니다. 비교가 'comboVendor.SelectedIndex == FirstIndex'라면 훨씬 더 깨끗하게 읽을 수 있습니까?
Roland Tepp

2

0와 같은 의미를 명확하게하기 위해를 상수 로 대체했을 것 NewVendorIndex입니다. 주문이 변경되는지 알 수 없습니다.


1

그것이 교수님의 총체적인 선호입니다. 일반적으로 리터럴을 여러 번 사용할 경우 상수를 사용하고, 라인의 목적이 무엇인지 독자에게 명확하게 알리거나 나중에 리터럴이 변경 될 수 있으며 변경하려는 경우에만 상수를 사용하십시오. 한 곳에서. 그러나 이번 학기에는 교수가 사장이므로 지금부터는 그 수업에서하겠습니다.

기업 세계를위한 좋은 훈련? 아마 가능합니다.


2
"리터럴이 여러 번 사용될 경우 상수 만 사용하십시오"부분에 동의하지 않습니다. 0 (그리고 아마도 -1, 1)으로 종종 분명합니다. 대부분의 경우 코드를 읽는 것이 더 분명한 이름을 지정하는 것이 좋습니다.
johannes

1

솔직히 말해서, 귀하의 코드가 모범 사례라고 생각하지는 않지만 그의 제안은 솔직히 조금 괴상합니다.

.NET 콤보 박스에 대한보다 일반적인 방법은 "Select .."항목에 빈 값을 제공하고 실제 항목에는 의미있는 값을 부여한 다음 수행하는 것입니다.

if (string.IsNullOrEmpty(comboVendor.SelectedValue))

오히려

if (comboVendor.SelectedIndex == 0)

3
귀하의 예에서 null은 단순히 또 다른 리터럴입니다. 이 수업의 핵심은 리터럴을 피해야한다는 것입니다.
overslacked

@overslacked-내 예제에는 null 리터럴이 없습니다.
Carson63000

null 리터럴이 있더라도 null은 사용할 수있는 리터럴이지만 null과 같은지 확인하지 않고 객체에 대한 참조가 null인지 확인하는 방법이 없다고 생각합니다.
Ramhound

Carson63000-나는 당신의 IsNullOrEmpty 사용을 언급하고있었습니다. 하나의 "마술 가치"를 다른 것으로 바꾸고 있습니다. @Ramhound-Null은 어떤 경우에는 허용되는 리터럴이며 의심의 여지가 없지만 이것이 좋은 예라고 생각하지 않습니다 (마법 값으로 null 또는 blank 사용).
오버 랙

"약간의 괴기 한"인 경우 -1입니다. 선택한
인덱스를

1

그는 상수 사용의 가치를 강조하는 데 잘못이 아니며 리터럴을 사용하는 데 잘못이 없습니다. 그가 이것이 예상되는 코딩 스타일이라고 강조하지 않는 한, 리터럴은 해롭지 않기 때문에 사용에 대한 마크를 잃어서는 안됩니다. 상용 코드에서 리터럴이 여러 번 사용되는 것을 보았습니다.

그의 요점은 좋다. 이것은 상수의 이점을 인식하게하는 그의 방법 일 수 있습니다 .

1-실수로 조작되지 않도록 코드를 어느 정도 보호합니다

@DeadMG가 2-As에 따르면, 동일한 문자 값이 여러 곳에서 사용되면 실수로 다른 값으로 나타날 수 있으므로 상수는 일관성을 유지합니다.

3 상수는 유형을 유지하므로 0을 의미하기 위해 0F와 같은 것을 사용할 필요가 없습니다.

4의 경우 읽기의 용이성, COBOL의 값은 제로에 대한 예약 된 단어로 ZERO를 사용 (하지만 당신은 문자 그대로 제로 사용할 수 있습니다) - 그래서, 예를 들어, 이름은 때때로 도움이되는 값을 제공 : (출처 : MS-상수

class CalendarCalc
{
    const int months = 12;
    const int weeks = 52; //This is not the best way to initialize weeks see comment
    const int days = 365;

    const double daysPerWeek = (double) days / (double) weeks;
    const double daysPerMonth = (double) days / (double) months;
}

또는 귀하의 경우 (@Michael Krussel 답변에 표시된)


2
그것이 일주일 동안 이상한 정의가되지 않습니까? 7 일이 있습니다 일주일하지 7.4287143
윈스턴 Ewert

@WinstonEwert, 귀하의 의견에 감사드립니다. 365/52 = 7.01923076923077 = 7 + (1/52). 이제 소수 부분을 제거하고 7 * 52를 계산하면 1 년의 정확한 일수가 아닌 364 일이됩니다. 분수를 잃어버린 것보다 분수가 더 정확합니다 (숫자 만 표시하려면 결과를 7로 표시하도록 형식을 지정할 수 있으므로). 어쨌든, 상수에 관한 MS의 예일 뿐이지 만 요점은 흥미 롭습니다.
NoChance

1
물론 그 예는 하나이지만 분수를 포함하는 것이 더 정확하다는 진술에 반대합니다. 1 주일은 7 일로 정의됩니다. 26 주가 182.5 일이라는 정의에 따르면 그것은 정확하지 않습니다. 실제로 문제는 int weeks = 52입니다. 연간 52 주가 없습니다. 1 년에 52.142857142857146 주가 있으며, 그 수는 분수를 유지해야합니다. 물론 전체 상수 집합에서 실제로 일정한 유일한 것은 개월 수입니다.
Winston Ewert

0

복잡한 파생이 있거나 자주 반복되는 경우에만 상수로 저장하면됩니다. 그렇지 않으면 리터럴이 좋습니다. 모든 것을 일정하게 유지하는 것은 완전히 과잉입니다.


자주 두 번 생각하고 코드를 수정할 필요가없는 경우에만. 두 가지 경우 중 하나를 변경하여 버그를 만드는 것이 정말 쉽습니다.
BillThor

0

실제로 언급했듯이 위치가 변경되면 어떻게됩니까? 할 수 있거나해야 할 일은 색인에 의존하기보다는 코드를 사용하는 것입니다.

따라서 선택 목록을 만들면 html과 같이 끝납니다.

<select>
    <option value='CREATE'>Create New Vendor...</option>
    <option value='1'>Existing Vendor</option>
    <option value='2'>Existing Vendor 2</option>
    <option value='3'>Existing Vendor 3</option>
</select>

그런 다음을 확인하는 대신 selectedIndex === 0값이 CREATECODE일정하며이 테스트와 선택 목록을 작성할 때 사용 된 값인지 확인 하십시오.


3
아마도 좋은 접근 방법 일지 모르지만 C #을 사용함에 따라 html은 가장 희망적인 예제 코드가 아닙니다.
Winston Ewert

0

나는 그것을 완전히 제거 할 것입니다. 콤보 상자 목록 옆에 새 만들기 버튼을 넣으십시오. 목록에서 항목을 두 번 클릭하여 편집하거나 단추를 클릭하십시오. 콤보 박스에 새로운 기능이 내장되어 있지 않습니다. 그런 다음 마법 번호가 모두 제거됩니다.

일반적으로 코드의 리터럴 숫자는 상수를 정의하여 숫자 주위에 컨텍스트를 배치해야합니다. 제로 란 무엇입니까? 이 경우 0 = NEW_VENDOR입니다. 다른 경우에는 다른 의미가있을 수 있으므로 가독성과 유지 관리 성이 컨텍스트를 둘러싼 것이 좋습니다.


0

다른 사람들이 말했듯이 인덱스 번호 이외의 다른 방법을 사용하여 주어진 동작에 해당하는 콤보 상자 항목을 식별해야합니다. 또는 프로그래밍 논리가있는 색인을 찾아 변수에 저장할 수 있습니다.

내가 쓰고있는 이유는 "메모리 사용"에 대한 귀하의 의견을 제시하기 위해서입니다. C #에서 대부분의 언어에서와 같이 상수는 컴파일러에 의해 "접 힙니다". 예를 들어, 다음 프로그램을 컴파일하고 IL을 검사하십시오. 컴퓨터 메모리는 물론 모든 숫자가 IL에 들어 가지 않는다는 것을 알 수 있습니다.

public class Program
{
    public static int Main()
    {
        const int a = 1000;
        const int b = a + a;
        const int c = b + 42;
        const int d = 7928345;
        return (a + b + c + d) / (-a - b - c - d);
    }
}

결과 IL :

.method public hidebysig static 
    int32 Main () cil managed 
{
    .maxstack 1
    .locals init (
        [0] int32 CS$1$0000
    )

    IL_0000: nop
    IL_0001: ldc.i4.m1  // the constant value -1 to be returned.
    IL_0002: stloc.0
    IL_0003: br.s IL_0005

    IL_0005: ldloc.0
    IL_0006: ret
}

따라서 상수 산술을 사용하여 상수, 리터럴 또는 킬로바이트 코드를 사용하더라도 값은 문자 그대로 IL에서 처리됩니다.

관련 사항 : 상수 접기는 문자열 리터럴에 적용됩니다. 많은 사람들은 이와 같은 호출이 너무 불필요하고 비효율적 인 문자열 연결을 초래한다고 생각합니다.

public class Program
{
    public static int Main()
    {
        const string a = "a";
        const string b = a + a;
        const string c = "C";
        const string d = "Dee";
        return (a + b + c + d).Length;
    }
}

그러나 IL을 확인하십시오.

IL_0000: nop
IL_0001: ldstr "aaaCDee"
IL_0006: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_000b: stloc.0
IL_000c: br.s IL_000e
IL_000e: ldloc.0
IL_000f: ret

결론 : 상수 표현식의 연산자는 상수 표현식을 생성하며 컴파일러는 모든 계산을 수행합니다. 런타임 성능에는 영향을 미치지 않습니다.

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