2010-02-08 8 views
39

동료가 방금 C#에서 다음과 같은 구성을 만들었습니다 (예제 코드가 단순화되었습니다). 그의 목표는 나머지 코드에서 미리 정의 된 모든 문자열에 대한 표기법을 줄이는 것이 었습니다.C# 미리 정의 된 문자열에 대한 정적 클래스와 구조체

public struct PredefinedStrings 
{ 
    public const string VeryLongName = "Very Long Name"; 
    public const string AnotherVeryLongName = "Another Very Long Name"; 
    public const string TheLastVeryLongName = "The Last Very Long Name"; 
} 

public static void MethodThatUsesTheNames() 
{ 
    Console.WriteLine(PredefinedStrings.VeryLongName); 
    Console.WriteLine(PredefinedStrings.AnotherVeryLongName); 
    Console.WriteLine(PredefinedStrings.TheLastVeryLongName); 
} 

은 그를 위해 잘 작동하는 것 같다 있지만, 나는 그가 정적 클래스 대신 구조체를 사용해야 또는이 있다면 더 우아한 방법은 이것을 달성 할 것인지 궁금 중지 할 수 없습니다.

이렇게하는 것이 바람직한 방법은 무엇입니까? 이유를 설명하십시오.

+5

동료에게 명성을주십시오! 동료는 거의 const를 사용하지 않으며 코드 전체에 문자열 리터럴이 흩어져 있습니다! lol 정적 클래스는 일종의 표준이라고 생각합니다. –

+0

나는 이것을하는 것에 대해서 생각하고 있지만, 내가 과도하게 공학적이라고 느끼고있다. 일반적으로 문자열 리터럴을 처음에는 흩어 놓은 다음 다시 다른 메서드 나 클래스에서 동일한 문자열을 필요로하면 정적 클래스로 추출합니다.하지만 약간 지루할 수 있습니다. – ozzy432836

답변

34

이있다 나쁜 아무것도하지 않습니다 new PredefinedStrings()을하고 다른 코드를 중지 아무것도하지만 수 있도록 의미 혼란 무언가이다. 정적 클래스를 사용하면 컴파일러가 생성을 금지합니다. 정적 클래스가 프레임 워크에 상수를 제공하는 기본 방법이라는 것은 말할 나위도 없습니다. 나는 이후 검색하고 합리적으로 신속하게 System.Net.Mime.DispositionTypeNamesSystem.Net.WebRequestMethods.Http을 발견했다 -

편집 나는 증거가없는 두 번째 부분은 말했다, 추가 할 수 있습니다.

+0

아마도 구조체를 사용하면 처음에는 눈살을 찌푸리게 만들었지 만, '협약'을 점검하는 것을 생각하지 마십시오. 머리를 가져 주셔서 감사합니다. 이 답변은 구조체와 정적 클래스 중 하나를 선택하는 데 매우 유용하며 작업을 수행하기에 충분할 것입니다. 그러나 여기서는 리소스 파일을 사용하는 것이 적합한 지 여부를 확인해야합니다. –

+0

문자열이 바뀔 가능성은 극히 적기 때문에이 특정 상황에 적합한 것으로 보아이 답변을 수락합니다. 리소스 파일을 사용하는 것은 흥미롭지 만 현재 코드에 너무 많은 복잡성을 추가합니다. –

0

이 연습을 위해 Dictionary<enumNameType, string>을 사용합니다. 여기서 enumNameType은 (당신의 경우에) 가질 수있는 다른 유형의 이름입니다 ...이 사전은 정적 클래스로 래핑되고 캐시됩니다 - 우리는 처음 사용할 때만 생성 한 다음 동일한 객체를 반환합니다 ...

이 정보가 도움이되기를 바랍니다. struct 솔루션을

+0

상수 값을 사용하는 것의 이점은 무엇입니까? 사전을 사용하면 빠른 검색을 할 수 있습니다. 그렇지만 상수 값을 직접 참조하는 것보다 빠릅니다. –

+0

@Dan 이점은 열거 형에서 명명법을 다시 사용한다는 점입니다. 우리는 의미론이 필요로하는 모든 곳에서 사용할 수 있으며,이 명사구를 나타내는 열거 형은 사전에서 사용자에게 친숙한 명명법과 연결됩니다. – anthares

+0

실제로 enum *에서 문자열을 가져 오는 효율적인 방법에 대해 이야기하는 것 같습니다. OP가 문자열 값이 일정한 경우에만 관심이 있다는 인상을 받았습니다. 그러나 나는 틀릴 수 있습니다. –

5

이 코드에는 기능상의 문제가 없습니다. 그러나 stylistically 정적 클래스가 더 나은 동의합니다. 정적 클래스는 유형의 의도가 정적/상수 데이터 만 보유한다는 것을 선언합니다.

27

주로 리소스 파일에있는 문자열을 선호하며 코드 내에 포함되지 않습니다 (주로 국제화 이유로 사용). 그런 다음 값을 속성 멤버로 사용하여 정적 클래스를 통해 액세스 할 수 있습니다.

+2

+1, 답변입니다. 국제화뿐만 아니라 리소스 파일을 사용하면 전체 앱을 다시 빌드하지 않고도 오류를 수정하거나 문자열을 업데이트 할 수 있습니다. –

+3

웃기는 나는이 대답보다 일찍 똑같은 말을했다 .. 내 upvotes은 어디입니까 ?? : P –

+3

이 경우에는 문자열이 변경되지 않을 것이라는 확신이 있습니다. 리소스 파일을 사용하면이 특정 상황에서 과도한 공격이 될 수 있습니다. 정적 클래스가 작업을 수행합니다 (현재). 그러나 나는 미래의 사용을 염두에두고 이것을 지킬 것이다. 감사! –

22

static classstruct 이외에도 상수 문자열에 resource 개의 파일을 사용하지 않으시겠습니까? 이들은 SomeNamespace.ResourceName.KeyName으로 매우 쉽게 접근 할 수 있으며 프로젝트에있는 위치에 따라 필요한 경우 다시 컴파일하지 않고 외부에서 관리 할 수 ​​있습니다. ...

+1

타임 스탬프를 확인하면 1 분 후, +1을 드리겠습니다. – Andrew

+1

LOL thanks. 내가 너의 것을 더 일찍 upvoted ... –

1

정적이 더 좋으며 여기에 제 추론이 있습니다. 이 코드가 일부 라이브러리에 있고 다른 코드가이 라이브러리를 사용하는 경우 상수 필드의 값이 변경되면이 라이브러리를 다시 컴파일해야 할뿐만 아니라이 코드를 사용하는 코드를 다시 컴파일해야합니다. 도서관도. 그 이유는, 컴파일은 참조 할 때마다 상수 값을 삽입하기 때문입니다. 정적을 사용하는 경우 필드이 아니며 값이이 아니므로이 문제가 발생하지 않습니다.

0

나는 구조체를 상수에도 사용하지만 공용 API에는 내부 용으로 만 사용합니다. 열거 형 (enum)도 구조체로 변환되기 때문에 자연 스럽습니다.

5

리소스 파일 (.resx)을 찾는 것처럼 들립니다. 그러한 문자열을 저장하기에 알맞은 곳이며, 문자열을 .resx로 추상화하면 나중에 응용 프로그램을보다 쉽게 ​​현지화 할 수 있습니다. 자세한 내용은 http://msdn.microsoft.com/en-us/library/1ztca10y.aspx에있는 MSDN 페이지를 참고하십시오.

5

구조체 크기가 약 16 바이트 여야한다는 권장 사항을 잊지 마십시오. 주어진 32 비트 시스템은 바로 거기에 4 개의 System.String 참조입니다. 문자열 수가 증가하면 정적 클래스를 사용하는 것이 나을 것이라고 생각합니다.

+0

좋은 지적. 나는 그 코드를 일찍 읽은 것을 기억하지만, 오랫동안 연습하지 않았습니다. 왜냐하면 대부분의 코드가 구조체에 적합하지 않다고 생각하기 때문입니다 :-) –

9

간단한 경험 법칙 : 다른 선택의 여지가 없어 질 때까지 구조체를 사용하지 마십시오.

  • 단순한 유형이 사용될 수있다 (문자열, 수치 등)
  • 상수 참조 조립체에 주입되어

    상수는 몇 가지 단점을 가지고있다. 당신이 상수 조립 재 컴파일 상수를 사용하여 어셈블리를 다시 컴파일하지 않는 경우, 당신은 내가 이런 식으로 코드를 작성합니다

곤경에 얻을 것이다 (통지 이름 바꾸기가 너무 리팩토링) :

public static class KnownNames 
{ 
    public static readonly string VeryLong = "Very Long Name"; 
    public static readonly string AnotherVeryLong = "Another Very Long Name"; 
    public static readonly string TheLastVeryLong = "The Last Very Long Name"; 
} 
+2

const 대신에 '정적 읽기 전용'을 사용하는 이유를주의하십시오. Const는 컴파일 타임으로 평가 될 예정이며 의도 한 용도에는 적합합니다. –

+2

단순한 유형과 컴파일 된 값의 단점을 나열했습니다. 100 % 확신 할 수 없다면 const를 사용하십시오 (예 : Math.Pi와 같은) –

+1

정교함을 위해 고마워요. 값이 변하기를 기대하지는 않지만 끝없는 지혜로 값을 변경하기로 결정한 사람은 알 수 없다 ;-) –

1

정적 수업은 가장 표준적이고 기대하기 때문에 가기에 가장 좋은 방법 인 것 같습니다. 구조체/const 버전이 빠를 것이라고 생각했지만 일부 테스트 후에는 그렇지 않습니다.

길이, 비교, 연결, 사본, indexOf 및 하위 문자열을 포함하는 빠른 테스트의 결과는 다음과 같습니다. 디버거가 연결되지 않은 채 릴리스 된 .Net 4.0에서 실행되었습니다.

          .Net 3.0 .Net 4.0 
static class with static read-only string: 0.217 0.364 seconds 
static class with const   string: 0.211 0.361 seconds 
struct  with static read-only string: 0.211 0.372 seconds 
struct  with const   string: 0.214 0.371 seconds 
Properties.Resources    string: 1.173 1.268 seconds 

리소스 파일을 사용할 때를 제외하면 모두 거의 동일한 성능을 보였으 나 속도는 느립니다. Properties.Resources는 느리지 만 실행 파일에 저장되지 않으므로 경우에 따라 적절할 수 있습니다. 그래서 "정적 클래스"또는 Properties.Resources 내 의견을 문자열을 저장하십시오.

1

구조체는 일반적으로 this answer에 설명 된 특정 기준을 충족하지 않으면 피할 수 있습니다.

동료가 값을 저장하는 데 사용하지 않으므로 구조가 아닌 클래스를 사용해야합니다.

0

상수로 의도 된 새 개체를 만들 수 있다는 간단한 사실은 나쁜 습관 (일반적으로)의 분명한 증거입니다. .NET은 개념을 가끔 사용하기 때문에 "보통"이라고 말하지만, 이유는 확실하지 않습니다. 물론

, 당신은 항상이 같은 물건을 수행 할 수 있습니다

public class Foo 
{ 
    public struct Bar 
    { 
     public static double A = 100; 

     public Bar(double a) 
     { 
      A = a; 
     } 
    } 
} 

기술적 Bar의 생성을 정당화 않는; 그러나 상수 인 Bar이 (심지어 단일 스레드 환경에서도) 동일 할 것이라는 보장은 없으며 궁극적으로 거의 사용되지 않습니다.

관련 문제