我试图理解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>
类型 - 只允许使用T2
。 Foo<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}} ......有点奇怪。
答案 0 :(得分:2)
考虑以下类型:
public class Base {
public static int Value;
public class Nested { }
}
public class Derived:Base { }
什么是Derived.Value
和Derived.Nested
。实际上,当您通过派生类引用继承的静态成员(被认为是静态成员的嵌套类)时,您只需引用基类成员,因此在编译时它与Base.Value
和Base.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>.Nested
或A
!= C
,则B
和D
被视为不同的类型。它们可以在内部共享相同的实现,但对于赋值兼容性,它们是不同的Foo<T>.Private2.Nested
只是Foo<T>.Private1<Foo<T>>.Nested
的别名。即使class Bar:Foo<A>{}
,类Foo<A>.Private1<Foo<A>>.Nested
和Foo<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",因此需要彻底的转换(因为强制转换绑定到继承层次结构) )。