c#如何处理嵌套(泛型)类型?

时间:2015-02-27 21:52:37

标签: c# types nested

我试图理解C#视图在嵌套方面的类型 更具体地说,我试图理解为什么某些类型不被认为是赋值兼容甚至可转换的,当有"类型的"只存在一个嵌套类的定义。编译器/ CLR是否实际为这些类型生成了不同的类型,或者正在发挥什么规则......

示例代码:

public class Foo<T>
{
    protected class Private2 : Private1<Foo<T>>
    { }

    protected class Private1<T2> where T2 : Foo<T>
    {
        public sealed class Nested
        {
            public void Test(T2 foo)
            {
                foo.Method2(this); //Nope!
                var nes = (Private2.Nested)this; //Nope!
            }
        }
    }

    public void Method1()
    {
        var nested = new Private2.Nested();
        nested.Test(this);
    }

    private void Method2(Private2.Nested nested)
    {
        // something code...
    }
}

因此,即使嵌套实例创建为Private2.Nested,也无法将其转换为该类型。而且......好吧......鉴于Nested实际上是密封的,不同的嵌套类型如何相互关联? (他们不能互相继承吗?但另一方面,他们的实施应该100%相同......我错了吗?)

主要问题:当编译器&#34;编译&#34;这个嵌套类?实际生成了多少个唯一类型(不包括与valuetype相关的类型),如果它是全部&#34;相同&#34;类型,是人为的限制(如不安全的演员实际工作)? (我所说的是所有这些类型的IL来自相同的代码定义 - 所以在某种程度上编译器必须知道。这些类型的实例除了类型名称之外不是一点一点的相同?)


次要问题:不是我在这里真正要求的,主要是为了简洁/背景:是否有一些简单的改变可以使上述工作?我错过了一些明显的东西吗

永远不能在Foo<T>内直接引用Private1<T2>类型 - 只允许使用T2Foo<T>只是我用10~20个泛型类型讨厌泛型类的例子。它只是一个&#34;解决方法&#34;因为无法使用其类型别名泛型类:

public class Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair>
{
    //If only this was real...
    using BarT = Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair>;

    public void Method1(BarT bar) { ... } //so good!!

    //goodbye readability... see you never...
    public void Method2(Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair> whatIsThisVariable) { ... }
}

目的:避免多个屏幕范围和 完全 不可读的字段和方法参数类型! &gt; :(

...作为附注,我真的希望this可以用作类和接口中的类型,如Private2 : Private1<this>中所示。好的,这不会起作用,因为它与方法上的扩展语法相冲突,但类似的东西,可能是<this><super><base>,如Method(<this> arg)或{ {1}} ......有点奇怪。

3 个答案:

答案 0 :(得分:2)

考虑以下类型:

public class Base {
    public static int Value;
    public class Nested { }
}
public class Derived:Base { }

什么是Derived.ValueDerived.Nested。实际上,当您通过派生类引用继承的静态成员(被认为是静态成员的嵌套类)时,您只需引用基类成员,因此在编译时它与Base.ValueBase.Nested具有完全相同的含义。没有单独的静态字段Derived.Value或单独的类Derived.Nested

public static void Test() {
    Derived.Value=10;
    Console.WriteLine(Base.Value);
    Base.Value=20;
    Console.WriteLine(Derived.Value);
    Base.Nested bn=new Derived.Nested();
    Derived.Nested dn=new Base.Nested();
    Console.WriteLine(typeof(Base.Nested).FullName);
    Console.WriteLine(typeof(Derived.Nested).FullName);
    Console.WriteLine(typeof(Base.Nested)==typeof(Derived.Nested));
}

原始答案:
如果Foo<A>.Private1<B>.Nested!= Foo<C>.Private1<D>.NestedA!= C,则BD被视为不同的类型。它们可以在内部共享相同的实现,但对于赋值兼容性,它们是不同的Foo<T>.Private2.Nested只是Foo<T>.Private1<Foo<T>>.Nested的别名。即使class Bar:Foo<A>{},类Foo<A>.Private1<Foo<A>>.NestedFoo<A>.Private1<Bar>.Nested仍然被认为是不同的类型。因此Foo<T>.Private1<T2>.Nested无法转换为Foo<T>.Private1<Foo<T>>.Nested,因为T2不是必需的Foo<T>

答案 1 :(得分:1)

你不是在想门户网站。你的内部类已经在T上推广。

public class Foo<T>
{
    private class Private2 : Private1
    { }

    private class Private1
    {
        public sealed class Nested
        {
            public void Test( Foo<T> foo )
            {
                foo.Method2( this ); //Yup
                var nes = (Private2.Nested)this; //Yup
            }
        }
    }

    public void Method1()
    {
        var nested = new Private2.Nested();
        nested.Test( this );
    }

    private void Method2( Private2.Nested nested )
    {
        // something code...
    }
}

答案 2 :(得分:0)

对主要问题的部分回答:

由于嵌套实例的类型正确(在Method1中实例化),因此可以通过更改Method2来接受一个对象并在运行时强制转换代码来编译代码。这似乎有用 - 只要Foo被密封 - 但只要其他人可以将Private1子类化,它就不再保证可以工作了。 (因此不是解决方案。)然而,测试这种方法显示:

  
    

Private2.Nested只是语法规则的结构 - 在结果变量GetType()上使用Private1.Nested并且没有Private2.Nested类型。

  

我认为我从这里得到的令人厌烦的感觉(以及为什么我认为密封与之相关)在区分子类型和继承方面是我的某种困惑。因为外部类是继承的(Private1和Private2),所以感觉就像继承一样,因此感觉它应该以某种方式可以转换。但如果我理解正确,它们只是相同的子类型:

  
    

实际上不需要并且实际上没有任何继承关系(因为密封的明确提示)因为"the inheritance hierarchy is distinct from from the subtype hierarchy",因此需要彻底的转换(因为强制转换绑定到继承层次结构) )。