2013-03-28 2 views
6

먼저, 제 질문의 다소 재미있는 이름을 사용하십시오. 나는 원어민이 아니기 때문에이 몇 인물에 내 생각을 표현하는 데 10 분이 걸렸습니다.제한된 수의 유형을 가진 사전

내가하려는 것은 int, string 또는 bool 중 하나의 값을 허용하는 C# 사전을 만드는 것입니다. 처음에 제 생각에는 제네릭을 사용하는 것이었지만, 제가 아는 한 하나의 유형을 가능한 값 유형으로 정의 할 수 있으며 "그 중 하나가 될 수 없습니다". object을 사용하는 것도 가능하지만 복싱은 상당히 성능이 좋은 것으로 보입니다.

이렇게 할 방법이 있습니까?

은 여기 내 마음에 와서 무슨의 샘플입니다 :

Dictionary<string, (string, int, bool)> foo = new Dictionary<string, (string, int, bool)>(); 
foo.Add("key1", "Hello, World!"); //Correct - Value is a string 
foo.Add("key2", 37); //Correct - Value is an int 
foo.Add("key3", true); //Correct - Value is a boolean 
foo.Add("key4", new Foobar()); //Compiler error - Value is a Foobar 

내 궁극적 인 목표는 다른 개발자를위한 라이브러리를 제공하는 것입니다. 이 기능을 통해 런타임 중에 변수를 정의하고 유형을 지정할 수 있어야합니다.

편집 :에 대해 // 파이어 폭스 '페이지를 달성하기 위해 내가 원하는 것을 매우 가까운 무언가가 설정

+2

제목을 편집했습니다. "[제목에"태그 "가 포함되어 있어야합니까?] (http://meta.stackexchange.com/questions/19190/)"합의가 "아니오, 그렇지 않아야합니다"로 표시되어야합니다. –

+0

고마워. 나는 이것을 아주 자주 보았고 일반적인 관행이라고 생각했습니다. –

+0

의견에 포함 된 링크를 읽어 보시기 바랍니다. 그것은 좋은 습관이 아니며 그것을 볼 때 고쳐줍니다. –

답변

6

에 dictionry을 제한 할 수 있습니다.

그런 다음, 추가 방법, 당신은 당신의 자신의 논리를 제공 할 수

샘플 코드

public class MyDic : IDictionary<object, object> 
{ 
    private Dictionary<object, object> privateDic= new Dictionary<object,object>(); 


    public void Add(object key, object value) 
    { 
     if (value.GetType() == typeof(string)) 
      throw new ArgumentException(); 
     privateDic.Add(key, value); 
    } 
    //Rest of the interface follows 
} 
+3

이 코드가 얼마만큼 바뀌는 지에 따라'Add' 메소드에 3 개의 별도 오버로드를 제공하고 각각'int','string' 또는'bool' 타입의'value'를 수락 할 수 있습니다. 이렇게하면 컴파일 타임에 형식 정확성이 검사되며 런타임에는 검사되지 않습니다. – dialer

+0

아마도 이것이 최선의 방법 일 것입니다. 고마워요. –

+0

@dialer : 귀하의 솔루션에는 컴파일 시간 검사의 장점이 있습니다. 데이비드가 타입을 주입하는 것과 같은 런타임 검사가 필요한지 모르겠다. –

0

에 내가 제안 :

  1. 는 예를 들어, 귀하의 사전 값에 대한 기본 형식을 만듭니다 MyDictionaryBaseType
  2. 귀하가 갖고있는 사전 값 유형마다이 기본 유형을 확장하십시오. StringDictionryType : MyDictionaryBaseType, IntegerDictionryType : MyDictionaryBaseType ... 등입니다.
  3. MyDictionaryBaseType을 사용하여 일반 사전 형식을 만들고이 기본 형식을 확장하도록 형식을 제한하십시오.

이 방법 당신은 IDictionary를 구현하고 개인 변수로 사전을 사용하는 신선한 새로운 클래스를 생성하지 왜 셋 개을 지정된 유형의

+0

누군가 왜 이것이 downvoted 이유를 설명해 주시겠습니까? –

+0

@DavidStockinger 나는 'int','bool' 및'string'에 대해 자신 만의 형식을 만들어 강제로 작업 할 것이기 때문에 추측합니다. 이론적으로 (즉, 그것 이외의), 그것은 매우 훌륭하고 깨끗한 해결책이다. – dialer

0

당신은이 같은 래퍼 클래스의 사용에 값을 넣을 수 있습니다 따라 실패 :

class Value 
{ 
} 

class TypedValue<T> : Value 
{ 
    public T Val; 
} 

class IntValue : TypedValue<int> 
{ 
} 

class StringValue : TypedValue<string> 
{ 
} 

class BoolValue : TypedValue<bool> 
{ 
} 

Dictionary<string,Value> foo; 

foo.Add("key1", new StringValue{Val="Hello World!"}); 

또 다른 가능성은 사전을 사용하고 올바르거나 잘못된 유형에 대한 런타임 검사를 추가하는 것입니다. 나는 권투를 포함하지 않고 해결책이 있다고 생각하지 않습니다.

0

달성하려는 작업은 유형에 따라 안전하지 않습니다. 예를 들어, 당신은 사전 있다고 가정 해 봅시다 :

var foo = new Dictionary<string, (string, int, bool)>(); 
var x = foo["key1"]; 
// What type is x? How could the compiler know? 

하나의 아이디어 중 하나 string, int, 또는 bool 하나의 보유 할 수있는 컨테이너 클래스를 고안하는 것입니다.

public class StringIntBool { 
    private bool _isSet; 
    private bool _isString; 
    public bool IsString { 
     get { return _isString; } 
    } 
    // ... 

    private string _innerString; 
    public string InnerString { 
     get { 
      return _innerString; 
     } 
     set { 
      if (_isSet) { 
       throw new Exception("StringIntBool is already set"); 
      } 
      _isSet = true; 
      _isString = true; 
      _innerString = value; 
     } 
    } 

    // etc... 
} 

이것은 꽤 못 생기고 많은 이점을 제공하지 않습니다.

대안으로 실제로 세 값을 모두 object으로 저장 한 다음 Functional C#과 같은 기법/라이브러리를 사용하여 많은 함수 언어와 마찬가지로 패턴 일치를 수행 할 수 있습니다.

object x = "str"; 
int res = x.Match() 
    .With<string>(s => s == "str" ? 10 : 20) 
    .With<int>(i => i) 
    .With<bool>(b => b ? 50 : 60) 
    .Return<int>(); 

이 프로그래밍 패턴은 실제로 특정 기능 언어에서 매우 일반적입니다. 예를 들어, SML에서 데이터 유형을 정의한 다음 필요에 따라 패턴을 일치시킬 수 있습니다.

(* StringIntBool *) 
datatype sib = SibString of string | SibInt of int | SibBool of bool 

val x = (* some instance of sib *) 
val y = case x of 
    SibString s => if s = "hello" then 50 else -50 
    | SibInt i => i 
    | SibBool b => if b then 10 else 20 
+0

F #에서 차별화 된 유니온을 사용하여 동일한 작업을 더 많이 또는 덜 할 수 있다고 생각한다. – JerKimball

관련 문제