일반 클래스에서 상속할 때 T의 목록 또는 열거자에 대한 제안 사항

StackOverflow https://stackoverflow.com/questions/53395

  •  09-06-2019
  •  | 
  •  

문제

나는 대답이 간단하지 않을 것이라는 것을 알고 있으며 이미 몇 가지 (내 생각에 추악한) 덩어리를 사용하고 있습니다.나는 단지 몇 가지 우아한 답변을 찾고 있을 뿐입니다.

추상 클래스:

public interface IOtherObjects;

public abstract class MyObjects<T> where T : IOtherObjects
{
   ...

   public List<T> ToList()
   {
       ...
   }
}

어린이들:

public class MyObjectsA : MyObjects<OtherObjectA> //(where OtherObjectA implements IOtherObjects)
{


}

public class MyObjectsB : MyObjects<OtherObjectB> //(where OtherObjectB implements IOtherObjects)
{


}

MyObject 컬렉션(또는 기타 유사한 그룹, 일반 또는 기타)을 반복하여 활용하는 것이 가능합니까? ToList 의 방법 내 개체 현재로서는 T의 유형을 구체적으로 알지 못하기 때문에 기본 클래스입니다.

편집하다구체적인 예를 들자면, 이런 일이 일어날 때마다 한동안 고민하고 대신 다른 일을 해왔기 때문에 현재 요구사항은 없습니다.그런데 꽤 자주 올라오니까 띄워야겠다고 생각했어요.

편집하다@Sara, 내가 관심 있는 컬렉션의 특정 유형이 아니며 List일 수도 있지만 여전히 각 인스턴스의 ToList 메서드는 익명 유형 없이는 상대적으로 사용할 수 없습니다.)

@aku, 사실입니다. 이 질문은 상대적으로 가설일 수 있지만 T개의 객체 목록을 검색하고 작업할 수 있으며 해당 기본 유형만 아는 것이 매우 유용합니다.ToList가 List Of BaseType을 반환하도록 하는 것이 내 해결 방법 중 하나였습니다.

편집하다 @ 모두:지금까지는 이것이 내가 바라던 종류의 논의였지만, 내가 의심했던 모든 것이 대부분 확인되었습니다.지금까지 모두 감사드립니다. 다른 분도 자유롭게 입력해 주세요.

편집하다@Rob, 예, 정의된 유형에 대해서는 작동하지만 유형이 IotherObjects 목록으로만 알려진 경우에는 작동하지 않습니다.

@롭 다시 감사해요.그것은 일반적으로 나의 투박한 해결 방법이었습니다 (무례하지 않습니다 :)).또는 ConvertAll 함수를 사용하여 대리자를 통해 다운캐스트합니다.시간을 내어 문제를 이해해 주셔서 감사합니다.

적격 편집 제가 조금 혼란스러웠다면

더 정확하게 말하면 (최신 구현으로 인해 너무 복잡해졌을 수도 있습니다):

객체 A에서 상속받은 B와 C라는 두 가지 객체 유형이 있다고 가정해 보겠습니다.

B 목록이나 C 목록, 또는 다른 경우 둘 중 하나의 목록에서 많은 시나리오가 제시되었습니다. 그러나 기본 클래스에 있는 경우 어느 것이 덜 구체적인 목록이 필요한지는 알 수 없습니다. ㅏ.

위의 예는 다음과 같은 내용을 희석시킨 예입니다. 덜 구체적인 목록 문제의 최신화.

일반적으로 작성이 필요한 코드의 양을 제한하고 다른 옵션보다 조금 더 우아해 보이는 가능한 시나리오를 통해 스스로 제시되었습니다.나는 가능성과 내가 어느 정도 알고 있는 다른 관점에 대해 토론하고 싶었습니다.지금까지 아무도 ConvertAll()을 언급하지 않았다는 사실에 놀랐습니다. 이는 제가 사용한 또 다른 해결 방법이지만 현재 시나리오에 비해 너무 장황하기 때문입니다.

@롭 다시 한번 그리고 사라

감사합니다. 하지만 제네릭의 정적인 맥락을 모두 이해하고 있으며 여기서 발생하는 문제도 이해하고 있다고 생각합니다.

우리 시스템의 실제 디자인과 제네릭 사용(저는 디자인에 참여했던 사람 중 한 명이었기 때문에 편견 없이 이것을 말할 수 있습니다)은 잘 이루어졌습니다.핵심 API로 작업할 때, 단순히 어떤 일을 하기에는 잘못된 범위에 있는 상황을 발견했습니다. 대신에 제가 좋아하는 것보다 약간 덜 우아하게 처리해야 했습니다. 아니면 게으른 것일 수도 있습니다. 저는 그 라벨 중 하나를 받아들일 것입니다).

내가 클러지라고 부르는 것에 대한 나의 불만은 주로 성능 저하가 될 수 있는 개체를 기본 값으로 변환하기 위해 레코드 세트를 통해 루프를 수행해야 한다는 것입니다.

나는 이전에 코딩할 때 이 문제를 발견한 사람이 있는지, 그리고 이 문제를 처리하는 데 나보다 더 영리하거나 적어도 더 우아한 사람이 있었는지 궁금합니다.

도움이 되었습니까?

해결책

당신이 가지고 있다면

class B : A
class C : A

그리고 당신이 가진 것은

List<B> listB;
List<C> listC;

상위 유형의 목록으로 처리하려는 유형

그럼 당신은 사용해야합니다

List<A> listA = listB.Cast<A>().Concat(listC.Cast<A>()).ToList()

다른 팁

왜 MyObject 컬렉션이 있습니까?목록이 없는 특별한 이유가 있나요?

귀하의 경우 MyObjectsA와 MyObjectsB에는 공통 전임자가 없습니다.일반 클래스는 다음에 대한 템플릿입니다. 다른 클래스는 공통 기본 클래스가 아닙니다.서로 다른 클래스에서 공통 속성을 갖고 싶다면 인터페이스를 사용하세요.당신은 전화할 수 없습니다 ToList 루프에서는 클래스마다 서명이 다르기 때문입니다.반환하는 ToList를 만들 수 있습니다. 사물 특정 유형보다는

여전히 ToList() 메서드에 액세스할 수 있지만 유형이 확실하지 않기 때문에 이것이 작동하지 않습니까?

foreach(var myObject in myObjectsList)
    foreach(var obj in myObject.ToList())
        //do something

물론 이것은 C# 3.0에서만 작동합니다.

var를 사용하는 것은 단지 목록에 어떤 유형이 포함되어 있는지 알아야 하는 요구 사항을 제거하는 것입니다.var가 타이핑을 동적으로 만들 것이라는 망상을 가지고 있다는 Frank의 의견과는 대조적입니다.

좋아요, 혼란스럽습니다. 다음 코드는 제게는 잘 작동합니다(호기심이 더 커졌습니다!).

// Original Code Snipped for Brevity - See Edit History if Req'd

아니면 제가 뭔가를 놓친 걸까요?

OP의 응답에 따라 업데이트

알았어 지금은 정말 혼란스러워..당신이 말하는 것은 당신이 목록을 얻고 싶다는 것입니다 입력됨 일반/추상 목록의 값?(따라서 하위 클래스는 관련이 없게 됩니다.)

유형이 하위/인터페이스 구현자인 경우 유형 목록을 반환할 수 없습니다. 일치하지 않습니다!물론 다음과 같이 추상 목록에서 특정 유형의 항목 목록을 얻을 수 있습니다.

    public List<OfType> TypedList<OfType>() where OfType : IOtherObjects
    {
        List<OfType> rtn = new List<OfType>();

        foreach (IOtherObjects o in _objects)
        {
            Type objType = o.GetType();
            Type reqType = typeof(OfType);

            if (objType == reqType)
                rtn.Add((OfType)o);
        }

        return rtn;
    }

제가 아직 여기에 있지 않다면 질문을 다시 말씀해 주시겠습니까?!(당신이 무엇을 운전하고 있는지 확신하지 못하는 사람은 나뿐인 것 같지 않습니다.)귀하의 일반 사항에 대한 오해가 있는지 확인하려고 노력하고 있습니다.

또 다른 업데이트 :D

그렇군요. 입력된 목록을 가져오는 옵션이 필요하거나 기본 목록이 필요한 것 같군요. 예?

이렇게 하면 추상 클래스가 다음과 같이 보입니다. ToList를 사용하여 구체적인 유형을 가져오거나 ToBaseList()를 사용하여 인터페이스 유형의 목록을 가져올 수 있습니다.이는 모든 시나리오에서 작동합니다.그게 도움이 되나요?

public abstract class MyObjects<T> where T : IOtherObjects
{
    List<T> _objects = new List<T>();

    public List<T> ToList()
    {
        return _objects;
    }

    public List<IOtherObjects> ToBaseList()
    {
        List<IOtherObjects> rtn = new List<IOtherObjects>();
        foreach (IOtherObjects o in _objects)
        {
            rtn.Add(o);
        }
        return rtn;
    }
}

업데이트 #3

이는 실제로 "어설픈" 해결 방법이 아닙니다(무례하게 생각하지 않음). 이것이 유일한 방법입니다.여기서 더 큰 문제는 디자인/그록 문제라고 생각합니다.문제가 있다고 하셨는데, 이 코드가 문제를 해결해 줍니다.하지만 다음과 같은 작업을 기대했다면:

public abstract class MyObjects<T> where T : IOtherObjects
{
    List<T> _objects = new List<T>();

    public List<IOtherObjects> Objects
    { get { return _objects; } }
}
#warning This won't compile, its for demo's sake.

그리고 거기에서 나오는 유형을 선택하고 선택할 수 있어야 합니다. ~할 수 있었다 당신은 그것을 할?!나는 당신이 제네릭의 요점이 무엇인지 실제로 이해하지 못하고 제네릭이 설계되지 않은 작업을 수행하도록 하려고 한다는 느낌을 받았습니다!?

나는 최근에 그것을 발견했습니다.

List<A>.Cast<B>().ToList<B>()

무늬.

내가 찾던 바로 그 기능을 수행합니다.

제네릭은 정적 시간 유형 확인에 사용됩니다. ~ 아니다 런타임 파견.런타임 디스패치에는 상속/인터페이스를 사용하고, 컴파일 타임 유형 보장에는 제네릭을 사용하세요.

interface IMyObjects : IEnumerable<IOtherObjects> {}
abstract class MyObjects<T> : IMyObjects where T : IOtherObjects {}

IEnumerable<IMyObjects> objs = ...;
foreach (IMyObjects mo in objs) {
    foreach (IOtherObjects oo in mo) {
        Console.WriteLine(oo);
    }
}

(물론 저는 목록보다 열거형을 선호합니다.)

또는 VB와 같은 적절한 동적 언어를 사용하십시오.:-)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top