필드의 접두사를 사용하지 않는 이유는 무엇입니까?


19

옛날에는 헝가리 표기법을 사용했습니다. 이제는 passé로 간주 되며 대부분 더 이상 사용하지 않지만 여전히 m_멤버 필드를 나타내는 접두사를 사용 합니다.

나를 위해 다른 사람의 코드를 읽고 있다면 이것을 볼 수 있습니다.

count = 3;

나는 그것이 count그 함수에 대한 지역 변수 라고 가정 하고 함수의 다른 곳에서 사용될 무언가를하고 있습니다. 내가 이것을 보면 :

m_count = 3;

나는 객체의 상태를 업데이트하고 있음을 즉시 깨닫는다.

Microsoft 스타일 지침에 따르면 잘못된 방법이 있습니다. 비공개 필드의 이름을 함수 내에 정의 된 임시 변수와 정확히 동일하게 지정해야합니다. 아니 m_, 단순한 밑줄조차도 아닙니다.

그렇습니다. 우리는 고유 한 코딩 스타일을 정의 할 수 있지만 다양한 정적 코드 분석 도구와 씨름해야합니다.

Microsoft 스타일로 바꾸어도 기쁘지만 왜 그런지 잘 알고 싶습니다 .

변수가 로컬 함수인지 멤버인지를 알 수없는 이유는 무엇입니까?

추신 : 이것은 필드 앞의 "this"키워드와 c #의 메소드에 관한 현재의 모범 사례는 무엇입니까? 하지만 나는 묻지 m_않고있다.this.

PPS 또한 Microsoft에서 매개 변수, 로컬 변수 및 개인 필드의 이름 명명 규칙이 동일한 이유는 무엇입니까?를 참조하십시오 .


9
C #에 this키워드가 없습니까? 당신은 사용하여 멤버를 참조 할 수 없습니다 this와 같은, this.count?
FrustratedWithFormsDesigner

3
m_ 접두사는 필드와 메소드 사이의 이름 충돌을 피하는 C ++-ism입니다. C #에서는 메서드 이름이 대문자, 필드가 소문자로 시작해야하므로 문제가되지 않습니다.
amon

4
2017 년에 코드를 인쇄하는 경우 문제가있는 것입니다. 다른 두 시나리오에서는 count메소드에서 선언되지 않았기 때문에 아무데도 나타나지 않았다는 것이 명백해야합니다 . 솔직히 "IDE에서 벗어난"주장은 정말 약합니다. 특히 IDE에서 작동하는 코드 검토 도구가 있기 때문에.
Andy


답변:


19

Windows 용 API를 작업 할 때 Microsoft는 'i', 'sz'등뿐만 아니라 'm_'을 사용하여 헝가리어 표기법을 사용하는 것이 좋습니다. 당시 IDE가 강력하지 않았기 때문에 유용했습니다. 이 정보를 당신에게 보여주기에 충분합니다.

반면에 C #은 처음부터 매우 강력한 IDE를 가지고 있습니다.

따라서 공개 정적 또는 보호 필드에 대해 Microsoft의 C # 명명 지침 에서 권장 사항을 제시했습니다 .

 DO use PascalCasing in field names.
 DO name fields using a noun, noun phrase, or adjective.
X DO NOT use a prefix for field names.

마우스로 마우스를 가져 가거나 CTRL + K + W를 누르고 멤버에 대한 모든 정보를 얻을 수있게되었으므로 Microsoft는 접두사가 잘못된 형식이라는 결정을 내 렸습니다. 그것들은 이미 해결 된 문제에 대한 수동 솔루션입니다.

개인 필드는 지침에서 구체적으로 제외되었지만 Microsoft는 개인 필드가 내부적으로 진행되는 경우에도 마찬가지라고 결론 지은 것으로 보입니다. .NET 4.5 또는 .NET Core에서 Resharper를 가리킬 경우 알 수 있습니다.

도구를 사용하십시오. 수동으로하지 마십시오.


2
Andy와 같은 대답 ... 그렇습니다 ... ... IDE 외부의 코드를보고있는 많은 상황이 있습니다. 예-(1) 병합 도구 (2) 코드 검토 도구. (3) (숨겨진) 인쇄물.
Betty Crokker 2016 년

Andy는 문자 그대로 내가 한 순간을 게시했습니다. "답변 추가"를 클릭하면 "1 개의 새 댓글"팝업이 나타납니다. 이러한 도구에 관해서는 두 도구가 이미 IDE에 있습니다. 인쇄물 ... 왜 그렇게합니까?
케빈 요금

1
내 초기 질문에 답이 없습니다 ... 그렇습니다. Microsoft는 m_를 사용하지 말고 도구 제조업체는 그에 따라 m_를 사용해야하는 기술적 이유가 아니라 종종 "권한에 대한 이의 제기"라고 말합니다. 내가 m_를 사용하지 않는 것으로 보인 유일한 기술적 이유는 Timothy Truckle에서 왔으며 그것을 이해하지 못합니다 ...
Betty Crokker

8
@BettyCrokker m_는 절대적으로 가치가 없기 때문에. IDE는 멤버에게 알리거나 알려주지 않으므로 m_은 중복됩니다. 왜 m_에 고정되어 있습니까? 왜 l_ (로컬 용)? 왜 afsdfjdskfjas_입니까? 어쨌든 그것은 어리석은 종교적 논쟁 때문에 질문을 내리려고합니다. 하고 싶은대로하세요. 당신은 또한 노크하고 가이드 라인은 "필드 명명 지침에 적용 말할 정적 공공 및 보호 분야 . 내부 및 민간 분야가있다 _not_ 가이드 라인을 적용 , 공공 또는 보호 예 필드 멤버 디자인 가이드 라인에 의해 허용되지 않습니다."
앤디

1
@BettyCrokker OK, 그러나 당신은 그 가정으로 만들어진 지침에 대해 묻고 있습니다. 또한 "아무도 허용되지 않는"통계적 오차 한계 내에서 C # 코드를 인쇄하기 때문에 해당 가정을 사용하는 정적 도구에 대해서도 불평하고 있습니다. 사용하는 통계 분석 도구를 모르지만 Resharper는 매우 구체적입니다. 개인 필드는 "_lowerCase"입니다. 모든 유형 또는 "UpperCase"의 공용 멤버 및 로컬은 "lowerCase"입니다. "m"을 절약하는 것은 어쨌든 꽤 멋지게 보입니다.
Kevin Fee

17

C #에는 전역 변수가 없으므로 로컬 변수와 클래스 필드 만 남습니다.

그리고 지역 변수가 너무 많으면 식별자가 하나인지 여부를 추적 할 수 없으므로 복잡성을 가장 심각하게 관리하기위한 지침 중 하나를 가장 잘 위반 한 것입니다.

매개 변수 객체를 추출하고 여러 간단한 함수로 함수를 분리하십시오. 유사성과 복잡성에 빠지지 않고 유지 관리 성을 고려하지 않는 한 코드를 리팩토링해야합니다.

함수 범위가 너무 작아야하고 전역 범위가 존재하지 않기 때문에 "이 멤버는"장식의 목적이 더 이상 유지되지 않는다는 것을 알았으므로 이러한 마커에는 한 가지 단점이 있습니다. 인수 / 지역 변수를 멤버로 이동하거나 다른 방법으로 이동하십시오.


일단 점을 찍으면 클래스 또는 네임 스페이스가 될 수도 있습니다.
코드 InChaos

3
나는 이것이 실제로 질문에 대답하지 않는다고 생각합니다.
Vladimir Stokic

5
@FrankHileman 사실입니다. 이름을 추리 할 이유가없는 이유를 설명합니다.
중복 제거기

2
"추방"? 이 경우 의견에 대한 질문입니다. 모든 사람들은 추악함에 대해 다른 의견을 가질 수 있습니다. 한 규칙을 다른 규칙보다 선호하는 이유는 있지만이 경우 표준 규칙은 없습니다.
Frank Hileman

1
@Dupuplicator의 아름다움은 보는 사람의 눈에 있습니다. 한때 추악하다고 생각한 규칙, 이제는 유용한 것으로 감사합니다.
Frank Hileman

11

개발자가 네임 스페이스 지시문을 사용하여 네임 스페이스를 추가하지 않는 이유는 무엇입니까?

System.DateTime()보다 훨씬 더 명확합니다 DateTime(). 내가 다루고있는 것을 정확하게 알려줍니다. 우리가 게으른 타이피스트이기 때문입니까?

아니요. 우리는 게으른 타이피스트이지만 그 이유는 아닙니다.

우리는 세부 사항을 무시하고 추상화에 집중할 수있는 코딩 스타일을 선호합니다. 구조 상세를 알리기 위해 이름을 강요하는 것은 산만하다. 복잡한 알고리즘을 작업 할 때 내가 작업하고있는 것에 대해 모든 세부 사항을 상기시켜주는 이름을 원하지 않습니다. 난 그냥 혼란에서 저를 유지하기 위해 이름이 필요 Timer하고 DateTime. 다른 곳에서 호환되는지 걱정할 것입니다.

팀에 Jon이라는 두 명의 남자를 원하지 않는 것과 같은 이유입니다. 이들이 성이라는 사실이 접두사 또는 접미사를 제공하는 이유는 아닙니다. 난 그냥 당신을 Skeet이라고 부를 것입니다. 더 이상 아무것도 평평한 고통입니다.


2
이것은 질문에 대답하지 않는 것 같습니다. .net에는 개인 필드에 대한 일반적인 환경 설정이나 규칙이 없습니다.
Frank Hileman

12
@FrankHileman 일반적으로 좋은 이름을 선호합니다. 규칙은 좋은 이름을 만들지 않습니다. 컨벤션은 McOhPlease Von StopItAlreadyStine과 같은 이름을 만듭니다.
candied_orange 2016 년

컨벤션은 다른 개발자 코드로보다 쉽게 ​​작업 할 수 있도록하기위한 것입니다. 귀하의 답변은 헝가리어를 다루지 만 개인 분야에 대한 협약은 없으므로 질문은 잘못된 가정에 근거합니다.
Frank Hileman

7

조금 확장 해 봅시다.

3 가지 공통 접두사 스타일이 있으며, 모두 C # 코드에서 가끔 발생합니다.

  • 미디엄_
  • _
  • 이.

이러한 접두사는 일반적으로 클래스의 개인 구현에 사용됩니다 . Microsoft 권장 사항은 주로 수업의 노출 부분에 관한 것입니다.

사용의 장점 m_이상은 _당신이 아니라 같은 # c를 사용하는 경우 접두사는 전체 코드베이스에 따라 변경 될 수 있다는 점이다 사용 언어 _접두사가 허용되지 않는 . *의 장점 m_이상이 this.이 짧은 점입니다 당신이 실수하지 않을 것이다 접두사를 잊어라.

_over 의 장점은 m_더 짧고 접두사로 시작하는 항목이 맨 위에 정렬되어 도구별로 알파벳순으로 정렬된다는 것입니다. _over 의 장점은 this.짧고 접두사를 실수로 잊어 버리지 않는다는 것입니다.

의 장점 this.을 통해 m_그리고 _당신이 코드베이스에서 사용할 경우 수 있다는 것입니다 _또는 m_수락 된 보편적 인 규칙이 아니다. 그것은 또한 아무도 규칙 _이나 m_규칙 을 알 필요가 없다는 것을 의미하며 , 이는 일을 더 단순하게 만드는 것으로 볼 수 있습니다. 단점은 컴파일러가이 접두사를 신경 쓰지 않기 때문에 this.접두사가 누락되어 표시기만큼 신뢰할 수없는 경우가 있습니다.


* _실제로 사용해서는 안되는 C ++ / CLI에서 사용하는 C # 클래스에 액세스하기 시작 _하면 공통 접두사에 동의하는 것이 이전보다 더 복잡하다는 것을 알 수 있습니다. 접두사를 갖지 않기로 결정하면 해당 소음이 제거됩니다. 이것을 Deduplicator의 답변과 결합하면 "접두사의 이점은 거의 무시할 수 있습니다" 라는 말로 표현할 수 있습니다. 그것을 써".


거기 에 유래에 오래된 질문 이 관련은.


1
좋은 비교. 그러나 접두사를 사용하지 않으면 실제로 잘 작동한다는 것을 알았습니다.
Phil1970

6

MS 스타일 가이드는 공용 및 보호 된 메서드 및 변수에 대해서만 설명합니다. 즉, 다른 개발자가 라이브러리를 사용하는지 확인할 수 있습니다.

Microsoft 라이브러리에는 개발자가 라이브러리를 소비하는 표준 모양과 느낌이 부여됩니다.

개인 또는 지역 변수에 원하는 스타일을 자유롭게 사용할 수 있습니다.

변수 접두사는 일반적으로 여러 가지 이유로 권장하지 않습니다

  • 그들은 틀릴 수 있고, 따라서 오도의 소지가 있습니다
  • 변수 유형으로 접두사를 작성하면 작성한 클래스를 처리하는 방법이 명확하지 않습니다.
  • 많은 규칙이 있으며 항상 동의하지는 않습니다. 다른 개발자가 도움이 될만한 정보
  • 멤버 변수의 경우이 'this'를 사용할 수 있습니다. 키워드는 범위를 나타내며 complier가이를 적용합니다.

2
원래 필자는 필드에 접두사를 전혀 사용하지 않았습니다. 나중에 IDE 드롭 다운 목록 상자를 사용할 때 모든 필드가 알파벳순 멤버 목록의 맨 위로 이동하기 때문에 다른 문자를 사용하면서 다른 "_"문자를 사용하는 것으로 전환했습니다. 많은 다른 개발자들이 작성한 코드를 읽을 때 표준 규칙이 없으면 성 가실 수 있습니다.
Frank Hileman

얼마 후 당신은 너무 많은 다른 스타일을 볼 수 있습니다. 스타일을 적용하려고하면 모든 것을 계속 리팩토링해야합니다.
Ewan

4
"그들은 잘못 될 수 있고 따라서 오도 할 수 있습니다"를 대부분의 경우에 적용하면 변수 나 함수의 이름을 지정하지 않아야한다는 사실을 빨리 알게됩니다. 그리고 나는 당신의 두 번째 글 머리 기호가 "당신이 만들지 않은 클래스"라고 말해야한다고 생각합니다. 또는 그렇지 않으면 그냥 이해하지 못합니다 ... 어쨌든 비공개 필드에 대해 하나의 밑줄 접두어가 비공식 표준 인 것처럼 들리기 시작합니다. 아마도 우리가 갈 방향입니다.
Betty Crokker 2018 년

컴파일러에서 일부 사항을 확인하므로 m_count는 멤버 변수가 아닐 수 있지만 this.count는 항상
Ewan

많은 ppl을 사용하지만 시간이 지남에 따라 상황이 바뀌면 작년에 '모범 사례'로 작성된 코드가 올해의 규칙과 일치하지 않는다는 것을 알 수 있습니다
Ewan

4

나를 위해 다른 사람의 코드를 읽고 있다면 이것을 볼 수 있습니다.

count = 3;

'count'는 해당 함수의 로컬 변수이며 함수의 다른 곳에서 사용될 무언가를하고 있다고 가정합니다.

그리고 C #의 스타일 규칙을 준수하는 소스 코드를 읽는 다면 절대적으로 옳을 것 입니다. 그러한 코드에서 :

this.count = 3;

필드에 값을 할당합니다.

count = 3;

지역 변수에 값을 할당합니다.

따라서 C #의 스타일 규칙은 명확하고 모호하지 않습니다. 접두사 가 필요 없기 때문에 접두사를 사용하지 않도록 강요합니다 .

저자는 대신 자신의 개인 규칙을 사용하기로 결정하는 소스 코드에 관해서는, 당신이 요청해야 그들을 그들이 그렇게 할 수있는 선택을 한 이유를 개인적으로. 밑줄과 같은 접두사를 사용하지 않으면서도 밑줄을 사용하지 않으면 this.코드를 읽기가 어려울뿐만 아니라 추가 규칙이 필요한 경우도 효과적으로 발생합니다.

public class Hello
{
    private string greetings;

    public Hello(string greetings)
    {
        greetings = greetings; // Wait, what is that?!
    }
}

C #에 this 키워드가 없습니까? this.count와 같이 이것을 사용하는 회원을 언급 할 수 없습니까?

예, 그러나 (1) 더 타이핑하고 (2) 잊기 쉽습니다. 필드 이름이 m_count이면 이것을 입력 할 필요가 없습니다.

그러나 여기서는 틀 렸습니다.

메모장에서 코드를 작성할 때 더 타이핑하는 것이 좋습니다. 자동 완성 기능을 가진 IDE 또는 더 나은, 인텔리 사이의 비교를 this.count하고 m_count명백한으로하지 않습니다. 밑줄을 입력 하려면 Shift+가 -필요합니다.

"잊기 쉬운"에 관해서는, 이것은 메모장 사용자들에게만 해당됩니다. StyleCop과 Resharper는 this.필요할 때 퍼팅을 잊을 수 있도록 해줄 뿐만 아니라 몇 시간의 프로그래밍 후에 this.필요할 때 퍼팅을 습관화합니다.


6
this필요할 때만 사용 하면 느낌이 일관되지 않고 너무 자주 산만 해집니다. 당신이 사용하고자하는 경우 this대신 접두사, 나는 당신이한다고 생각 항상 그것을 사용할 수 있습니다. 이 경우 접두사가되고를 사용할 수도 있습니다 _.
RubberDuck

1
RubberDuck이 맞습니다. "이." 컴파일러의 의미는 있지만 접두사입니다.
Frank Hileman

4

"멤버"접두사는 일종의 구현 세부 사항입니다. 가능한 리팩토링을 생각할 때 문제 영역에서 기술 솔루션 영역으로의주의를 산만하게합니다. – 나

더 설명해 주시겠습니까? 너의 이유는 내가 접두사를 사용하지 않는 이유에 대해 내가 본 유일한 이유이고 그것을 이해하지 못한다. 내가하지 말아야 할 이유와 동일하지 않습니다.) – Betty Crokker

내 요점은 @CandiedOrange와 @Ewan의 답변을 확장하는 것입니다.

접두사는 리팩토링을 어렵게 만듭니다.

코드가 발전함에 따라 변수와 메소드의 범위가 변경 될 수 있습니다. 예 : 개인 메소드를 작성하고 나중에 다른 (새로운) 클래스에서도 사용 가능해야한다는 것을 알 수 있습니다. 메소드 매개 변수 및 로컬 변수도 비슷할 수 있습니다.

세금 계산기를 생성한다고 가정 해 보겠습니다. 변수 의 임대 가시성 범위 원칙에 따라 세율기본 값 을 모두 매개 변수로 사용하는 방법으로 시작합니다 . (예 :
Java-ish ...)

class TaxCalculator{
   double Calculate(double p_TaxRateInpercent, double p_BaseValue){
     return (100+p_TaxRateInpercent)/100 * p_BaseValue;
   }
} 

다음으로 역 작업을 구현해야하며 TDD에 따라 최소한의 노력으로 작업을 수행하십시오.

class TaxCalculator{
   double Calculate(double p_TaxRateInpercent, double p_BaseValue){
     return (100+p_TaxRateInpercent)/100 * p_BaseValue;
   }
   double CalculateBase(double p_TaxRateInpercent, double p_TaxedValue){
     return p_TaxedValue/((100+p_TaxRateInpercent)/100);
   }
} 

다음 TDD는 코드를 리팩터링하여 두 메소드의 매개 변수 목록을 줄이는 깔끔한 코드가되도록합니다.
(예, 두 배의 계산을 먼저 추출하지만 요점을 알려 드리겠습니다 ...)
확실한 해결책은 세금을 생성자 매개 변수로 전달하여 세율을 멤버 변수로 변경 하는 것입니다.

class TaxCalculator{
   double m_TaxRateInpercent;
   TaxCalculator(double p_TaxRateInpercent){
     m_TaxRateInpercent = p_TaxRateInpercent;
   }
   double Calculate(double p_BaseValue){
     return (100+m_TaxRateInpercent)/100 * p_BaseValue;
   }
   double CalculateBase(double p_TaxedValue){
     return p_TaxedValue/((100+m_TaxRateInpercent)/100);
   }
} 

보시다시피 기존 방법의 모든 줄 을 변경해야했습니다 p_TaxRateInpercent.

문제는 클래스 전체에서 이름을 바꾸는 IDE의 지원없다는 것 입니다. 유일하게 문자열을 포함하는 생성자 또는 부분을 변경하는 검색 / 교체 를 도와줍니다 p_TaxRateInpercent.
IDE는 정의되지 않은 변수 이름에 대한 리팩토링을 변경할 수 있지만 메소드의 범위로 제한 될 수 있습니다

접두사가 없으면 메소드 서명 만 변경되었을 것입니다. 이름 바꾸기가 전혀 필요하지 않았습니다.


변경시 혼란스러운 SCM 히스토리 접두사

또한 SCM 은 로직이 변경되지 않았더라도 접두사 변경을 로직 변경으로 기록합니다! SCM의 역사는 중요한 기술을 숨기고 다른 사람의 (실제 논리) 변경과 충돌 할 위험을 높이는이 기술 변경으로 인해 복잡해집니다.


1

모든 멤버 변수에 _ 접두사를 사용합니다. 나는 'this'접두사를 싫어합니다. 일부는 올바른 일이라고 주장하기 때문에 코드베이스에 많은 소음 / 혼란을 더합니다. 단일 밑줄도 Microsoft 샘플에서 일반적인 관행입니다.

따라서 귀하의 예에서 나는 :

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