2009-06-12 8 views
3

개체를 일반 IList로 캐스팅하는 데 문제가 있습니다. 이 문제를 해결하기 위해 성명을 발표 할 그룹이 있지만이 작업을 수행하는 더 좋은 방법이 있어야합니다.C# Generics 및 주조 문제

이 내 현재의 방법입니다 :

values = BuildClause((IList<colFilter.ColumnType>)colFilter.Value, prefix); 

또는

values = BuildClause((IList<typeof(colFilter.ColumnType)>)colFilter.Value, prefix); 

또는

values = BuildClause((IList<colFilter.ColumnType.GetType()>)colFilter.Value, prefix); 
:

string values; 

if (colFilter.Value is IList<int>) 
{ 
    values = BuildClause((IList<int>)colFilter.Value, prefix); 
} 
else if (colFilter.Value is IList<string>) 
{ 
    values = BuildClause((IList<string>)colFilter.Value, prefix); 
} 
else if (colFilter.Value is IList<DateTime>) 
{ 
    values = BuildClause((IList<DateTime>)colFilter.Value, prefix); 
} 
else if (...) //etc. 

는 내가하고 싶은 것은 이것이다 , 형식 또는 네임 스페이스 이름 'colFilter은'내 예에서

이 colFilter.ColumnType는 int이며 (당신은 using 지시문 또는 어셈블리 참조가?)를 찾을 수 없습니다 :

이들 각각은이 컴파일러 오류가 발생합니다 문자열, 날짜 시간 등. 왜 이것이 작동하지 않는지 모르겠습니다.

아이디어가 있으십니까?

편집 :이 여기에 C# 2.0

편집 # 2

이다 인 BuildClause 방법 (I 각 유형에 대한 과부하를) 다음을 수행 무엇

private static string BuildClause(IList<int> inClause, string strPrefix) 
{ 
    return BuildClause(inClause, strPrefix, false); 
} 

private static string BuildClause(IList<String> inClause, string strPrefix) 
{ 
    return BuildClause(inClause, strPrefix, true); 
} 

private static string BuildClause(IList<DateTime> inClause, string strPrefix) 
{ 
    return BuildClause(inClause, strPrefix, true); 
} 
//.. etc for all types 

private static string BuildClause<T>(IList<T> inClause, string strPrefix, bool addSingleQuotes) 
    { 
     StringBuilder sb = new StringBuilder(); 

     //Check to make sure inclause has objects 
     if (inClause.Count > 0) 
     { 
      sb.Append(strPrefix); 
      sb.Append(" IN("); 

      for (int i = 0; i < inClause.Count; i++) 
      { 
       if (addSingleQuotes) 
       { 
        sb.AppendFormat("'{0}'", inClause[i].ToString().Replace("'", "''")); 
       } 
       else 
       { 
        sb.Append(inClause[i].ToString()); 
       } 

       if (i != inClause.Count - 1) 
       { 
        sb.Append(","); 
       } 
      } 

      sb.Append(") "); 
     } 
     else 
     { 
      throw new Exception("Item count for In() Clause must be greater than 0."); 
     } 

     return sb.ToString(); 
    } 

답변

5

메소드 오버로드 및 제네릭과 관련된 방법은 없습니다. 비슷한 것처럼 보이지만 매우 다릅니다. 특히 과부하를 사용하면 다른 작업을 사용하는 인수 유형에 따라 수행 할 수 있습니다. 제네릭은 사용하는 유형에 관계없이 과 정확히 일치하는을 수행 할 수 있습니다.

BuildClause 메서드가 오버로드되어 있고 모든 오버로드가 다른 유형 (사용 된 유형에 따라 다르지는 않지만이 경우에는 실제로 - 따옴표를 추가할지 여부 선택)이 아닌 다른 것을 수행하는 경우 궁극적으로, "유형이 이것 인 경우에, 유형이 저것을하는 경우에"와 같은 무언가를 말해야 할 것입니다 (나는 "스위치 온 유형"이라고 부릅니다).

또 다른 접근법은 "스위치 온 유형"로직을 피하고 다형성으로 대체하는 것입니다. StringColFilter : ColFilter<string>IntColFilter : ColFilter<int>이 있다고 가정하면 각각은 ColFilter<T>의 가상 메소드를 무시하고 자체 BuildClause 구현 (또는 BuildClause 처리에 도움이되는 일부 데이터)을 제공 할 수 있습니다. 그런 다음 ColFilter의 올바른 하위 유형을 명시 적으로 만들어야합니다.이 유형은 "스위치 온 유형"논리를 응용 프로그램의 다른 위치로 이동시키는 것입니다. 운이 좋으면 해당 논리를 응용 프로그램에서 처리 할 유형에 대한 지식이있는 곳으로 이동 한 다음 응용 프로그램의 다른 위치에 다른 Col 필터를 명시 적으로 만들고이를 일반적으로 처리 할 수 ​​있습니다 나중에.

는 다음과 같이 고려 : 물론

abstract class ColFilter<T> 
{ 
    abstract bool AddSingleQuotes { get; } 
    List<T> Values { get; } 
} 

class IntColFilter<T> 
{ 
    override bool AddSingleQuotes { get { return false; } }  
} 

class StringColFilter<T> 
{ 
    override bool AddSingleQuotes { get { return true; } } 
} 

class SomeOtherClass 
{ 
    public static string BuildClause<T>(string prefix, ColFilter<T> filter) 
    { 
     return BuildClause(prefix, filter.Values, filter.AddSingleQuotes); 
    } 

    public static string BuildClause<T>(string prefix, IList<T> values, bool addSingleQuotes) 
    { 
     // use your existing implementation, since here we don't care about types anymore -- 
     // all we do is call ToString() on them. 
     // in fact, we don't need this method to be generic at all! 
    } 
} 

도 ColFilter 따옴표에 대한 여부를 알아야하는지 여부의 문제에 당신을 얻을이,하지만 디자인 문제이고 또 다른 질문 :

을받을 권리가 나는 또한 다른 포스터들과 함께 문자열을 결합하여 SQL 문을 만드는 무언가를 만들려고한다면 더 쉽게 그리고 더 중요하게 더 안전한 매개 변수화 된 쿼리로 이동해야합니다.

2

함수 BuildClause()처럼 보입니다.

IList에서 확장자 메서드로 BuildClause()를 만들 수 있으며 값을 함께 추가 할 수 있습니다. 다른 유형의 .ToString() 메서드를 호출하기를 원한다고 가정합니다.

+0

코드를 실행합니다. 내가 한 값 = BuildClause (colFilter.Value, 접두사); 괜찮아 보인다. colFilter.Value가 IList 유형 인 것으로 확신되면 확인해야합니다. –

+0

그게 나를 위해 작동하지 않는 것, 난 컴파일러 오류가 발생 : 어떤 BuildClause 과부하가 있습니까? – Jon

0

IList의 형식은 컴파일 할 때 알아야합니다. 원하는 작업에 따라 목록을 IList 또는 IEnumerable (제네릭없이)로 캐스팅하고 객체를 반복 할 수 있습니다.

2

C# 3.0에서 제네릭을 제대로 사용하면 필요한 것을 얻을 수 있습니다 (C# 2.0에서는 형식을 지정해야 할 수도 있음). 당신의 BuildClause 방법이 일반적인 이루어지면, 그것은 자동으로 일반 매개 변수 (들)에 전달되어 어떤 유형에 소요 :

public IList<T> BuildClause<T>(IList<T> value, object prefix) 
{ 
    Type type = typeof(T); 
    if (type == typeof(string)) 
    { 
     // handle string 
    } 
    else if (type == typeof(int)) 
    { 
     // handle int 
    } 
    // ... 
} 

public class ColumnFilter<T>: 
    where T: struct 
{ 
    public IList<T> Value { get; set; } 
} 

var colFilter = new ColumnFilter<string> 
{ 
    Value = new { "string 1", "string 2", "string 3" } 
} 

IList<string> values = BuildClause(colFilter.Value, prefix); 

제네릭으로, 당신은 당신의 ColumnFilter의 ColumnType 속성을 삭제할 수 있습니다. BuildClause 메서드와 함께 일반적이므로 typeof (T)를 수행하여 형식을 쉽게 결정할 수 있습니다.

2

I am having trouble casting an object to a generic

주조는 런타임 작업입니다.

일반 사항은 컴파일 타임 정보입니다.

스트림을지나 가지 마십시오.

또한 올바른 매개 변수화 생성기를 사용하면 작은 따옴표가 추가됩니다.

1

나는 그 질문을 이해하지 못한다. 그것은 나를 위해 작동합니다. 그것은 캐스트를 떨어 뜨리는 것처럼 간단 할 수 있습니까? 내가 뭘 놓치고 있니?

using System; 
using System.Collections.Generic; 
using System.Text; 

namespace ConsoleApplication1 { 

    class Foo<T> : List<T> { 
    } 

    class Program { 
    static void Main(string[] args) { 

    var a = new Foo<int>(); 
    a.Add(1); 
    var b = new Foo<string>(); 
    b.Add("foo"); 
    Console.WriteLine(BuildClause(a, "foo", true)); 
    Console.WriteLine(BuildClause(b, "foo", true)); 

    } 

    private static string BuildClause<T>(IList<T> inClause, string strPrefix, bool addSingleQuotes) { 
     StringBuilder sb = new StringBuilder(); 

     //Check to make sure inclause has objects 
     if (inClause.Count == 0) 
     throw new Exception("Item count for In() Clause must be greater than 0."); 
     sb.Append(strPrefix).Append(" IN("); 
     foreach (var Clause in inClause) { 
     if (addSingleQuotes) 
      sb.AppendFormat("'{0}'", Clause.ToString().Replace("'", "''")); 
     else 
      sb.Append(Clause.ToString()); 
     sb.Append(','); 
     } 
     sb.Length--; 
     sb.Append(") "); 
     return sb.ToString(); 
    } 

    } 

}