c# - 将泛型类转换为其基本非泛型类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/710116/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 14:19:44  来源:igfitidea点击:

c# - cast generic class to its base non-generic class

c#generics

提问by Buthrakaur

I have following classes:

我有以下课程:

public abstract class CustomerBase
{
    public long CustomerNumber { get; set; }
    public string Name { get; set; }
}

public abstract class CustomerWithChildern<T> : CustomerBase
    where T: CustomerBase
{
    public IList<T> Childern { get; private set; }

    public CustomerWithChildern()
    {
        Childern = new List<T>();
    }
}

public class SalesOffice : CustomerWithChildern<NationalNegotiation>
{
}

The SalesOffice is just one of few classes which represent different levels of customer hierarchy. Now I need to walk through this hierarchy from some point (CustomerBase). I can't figure out how to implement without using reflection. I'd like to implement something like:

SalesOffice 只是代表不同级别客户层次结构的少数类之一。现在我需要从某个点(CustomerBase)遍历这个层次结构。如果不使用反射,我无法弄清楚如何实现。我想实现类似的东西:

    public void WalkHierarchy(CustomerBase start)
    {
        Print(start.CustomerNumber);
        if (start is CustomerWithChildern<>)
        {
            foreach(ch in start.Childern)
            {
                WalkHierarchy(ch);
            }
        }
    }

Is there any chance I could get something like this working?

我有没有可能得到这样的工作?



The solution based on suggested has-childern interface I implemented:

基于我实现的建议的 has-childern 接口的解决方案:

public interface ICustomerWithChildern
{
    IEnumerable ChildernEnum { get; }
}

public abstract class CustomerWithChildern<T> : CustomerBase, ICustomerWithChildern
    where T: CustomerBase
{
    public IEnumerable ChildernEnum { get { return Childern; } }

    public IList<T> Childern { get; private set; }

    public CustomerWithChildern()
    {
        Childern = new List<T>();
    }
}

    public void WalkHierarchy(CustomerBase start)
    {
        var x = start.CustomerNumber;
        var c = start as ICustomerWithChildern;
        if (c != null)
        {
            foreach(var ch in c.ChildernEnum)
            {
                WalkHierarchy((CustomerBase)ch);
            }
        }
    }

采纳答案by Mitchel Sellers

I believe that you want to make the lookup for the determination of doing to the walk an interface.

我相信你想对走界面做查找的决心。

So maybe add an "IWalkable" interface that exposes the information needed to do the walk, then you can create your method checking to see if the passed object implements the interface.

因此,也许添加一个“IWalkable”接口来公开执行步行所需的信息,然后您可以创建方法检查以查看传递的对象是否实现了该接口。

回答by Reed Copsey

"Is" and "As" only work on fully qualified generic types.

“Is”和“As”仅适用于完全限定的泛型类型。

See this MSDN discussionfor details including workarounds.

有关包括变通方法在内的详细信息,请参阅此 MSDN 讨论

The most common workaround I've seen is to add an interface to the mix that your CustomerWithChildren could implement, and check for that interface.

我见过的最常见的解决方法是向 CustomerWithChildren 可以实现的混合添加一个接口,并检查该接口。

回答by John Saunders

You could move the WalkHierarchy method to the base class and make it virtual. The base class implementation would only process the current node. For the CustomerWithChildern<T>class, the override would do an actual walk.

您可以将 WalkHierarchy 方法移动到基类并使其成为虚拟的。基类实现只会处理当前节点。对于CustomerWithChildern<T>班级,覆盖将进行实际步行。

回答by Adam Robinson

Explicitly with that method, no. However you can achieve the same functionality with an interface. In fact, you could just have your generic class implement IEnumerable. It's also worth noting that your class should also have "where T : CustomerBase" in order to ensure type safety.

明确地使用该方法,不。但是,您可以使用接口实现相同的功能。事实上,你可以让你的泛型类实现 IEnumerable。还值得注意的是,您的类还应该有“where T : CustomerBase”以确保类型安全。

回答by x0n

I think everyone hits this "issue" when first working with generic classes.

我认为每个人在第一次使用泛型类时都会遇到这个“问题”。

Your first problem is hinted at in your question phrasing: an open generic type is NOT the base class to a closed one. There is no OO relationship here, at all. The real base class is CustomerBase. An "open" generic type is like a half-completed class; specifying type arguments "closes" it, making it complete.

你的问题措辞暗示了你的第一个问题:开放泛型不是封闭泛型的基类。这里根本没有 OO 关系。真正的基类是 CustomerBase。一个“开放”的泛型类型就像一个半完成的类;指定类型参数“关闭”它,使其完整。

While you can do:

虽然你可以这样做:

Type t = typeof(CustomerWithChildern<>)

the condition

条件

typeof(CustomerWithChildern<>).IsAssignableFrom(CustomerWithChildern<Foo>)

will always be False.

永远是假的。

-Oisin

-Oisin

回答by Sunny Milenov

Try this:

尝试这个:

if(start.GetType().GetGenericTypeDefinition() == typeof(CustomerWithChildern<>))