English 中文(简体)
Cast from Generics<T> to specific SubClass
原标题:Cast from Generics<T> to Specific SubClass
  • 时间:2010-01-08 14:53:15
  •  标签:
  • c#
  • generics

我有这样的一类。

public class MyClass<T> where T : OneType
{
   T MyObj { get; set; }

   public MyCLass(T obj)
   {
   }
}

public class SubClass: MyClass<TwoType>
{
}

// snip for other similar class definition

http://www.un.org IType。

现在,我有这种通用方法。

public static MyClass<T> Factory<T>(T vd)
 where T : OneType
{
   switch(vd.TypeName)
   {
      case Constant.TwoType
          return new SubClass((TwoType)vd);
     // snip for other type check
   }
}

显然,哪些职能是检查<代码>vd的类型,并创建适当的<代码>MyClass。 唯一的问题就是上述法典获得汇编,我不知道为什么。

错误

不能将T表示给2Type

最佳回答

阿马齐格,我这样说:

return (new SubClass(vd as TwoType) as MyClass<T>);

return (MyClass<T>)(object)new SubClass((TwoType)(object)vd );

但是,

return (MyClass<T>)new SubClass((TwoType)vd );

没有工作。

<代码>as和(>>>的表示似乎有所不同。

问题回答

如Grzenio正确指出的那样,T类的表述不能转嫁给2Type。 汇编者并不知道,这种表述得到保证是“如果”你的声明所保证的,但汇编者在分析类型时并不考虑声明的含义。 相反,汇编者认为,T可以是满足限制的任何类型,包括从IType(但不是2Type)中得出的一种类型。 很显然,没有将三甲型六氯环己烷转换为二甲型六氯环己烷,因此也没有从T型异丙型转变。

你们可以把汇编者ool起来,让它说“well,把T当作物体处理,然后将物体投向2Type”。 沿途的每一步骤都是合法步骤——T可以被允许提出异议,而且可能从物体转至2Type,因此汇编者允许这样做。

然后,从次类动物到<代码>MyClass<T>,就会出现同样的问题。 同样,你可以首先反对这一问题。

然而,该法典仍然是错误的:

public static MyClass<T> Factory<T>(T vd) 
 where T:OneType 
{ 
   switch(vd.TypeName) 
   { 
      case Constant.TwoType 
       // WRONG
       return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd)); 
     // snip for other type check 
   } 
} 

为什么这是错误的? 这里考虑一切可能是错误的。 例如:你说:

class AnotherTwoType : TwoType { }
...
x = Factory<TwoType>(new AnotherTwoType());

发生了什么? 我们不称SubClass Constructionor,因为这一论点并非完全属于二Type,而是来自二Type的。 你可能不想开关,而不想开关。

public static MyClass<T> Factory<T>(T vd) 
  where T:OneType 
{ 
  if (vd is TwoType)
       // STILL WRONG
       return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd)); 
  // snip for other type check 
} 

这仍然是错误的。 再说一遍,想什么可能是错误的:

x = Factory<OneType>(new TwoType());

现在发生了什么? 论点是:双轨制,我们制作新的分册,然后试图将其转换为,但分册未转换为MyClass<OneType>,因此,这将在运行时间坠毁。

工厂的正确规范是:

public static MyClass<T> Factory<T>(T vd) 
  where T:OneType 
{ 
  if (vd is TwoType && typeof(T) == typeof(TwoType))
       return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd)); 
  // snip for other type check 
} 

这一点现在是否清楚? 您可以考虑一种完全不同的方法;,如果你需要这么多的 cast子和操作时间的打字,以说服汇编者,该守则是正确的,这证明整个东西都是坏的法典。

它不会在Net 3.5和以下工作:SubClass不是MyClass<T>任何T,其唯一类型是MyClass<TwoType>。 通用班子没有继承其模板类型,例如:MyClass<string>而不是一个子级MyClass<object>-在C#中完全不同。

不幸的是,我不知道用什么合理方法书写你的工厂方法。

我知道这是一个老的问题,但我认为,这个问题也值得回答why,这是不可能做到的(没有使用各种简单的工作方式)。

在使用通用物时,从某种意义上来说,你是采用模板代码。 汇编者对您的法典使用一套更为严格的规则,因为它在汇编最后版本时也必须汇编成册。

因此,当你以通用语创建班级或方法时,必须将其汇编成任何可能的组合:,这些组合遵守你对通用参数的限制。

因此,我甚至进一步简化了你的法典,以显示所发生的情况:

我先宣布3个班级。 父母和两名子女:

public class Super { }

public class Child : Super { }

public class Sister : Super { }

然后,我宣布了一种通用的方法,在我尝试测试这种方法,然后将这种方法用于儿童类型:

public void InvalidMethod<T>(T input)
  where T : Super
{
  Child castedReference = null;
  if (input is Child)
  {
    // This intuitively ought to be valid C#, but generates a compiletime error
    castedReference = (Child)input;
  }
  // Do stuff...
}

这给你留下了与原始问题相同的错误,尽管在理论上,它看起来像坚实法典。 然而,实际发生的情况是,如果《法典》在任何法律文本的操作时间可以编纂,则汇编者就会进行检查。 这就是我所说的,即你正在使用模板,因为如果你把“修女”方法称作你的类型参数,你会这样做:

public void InvalidMethod(Sister input)
{
  Child castedReference = null;
  // Following  if  is never true
  if (input is Child)
  {
    // Following statement is invalid C#
    castedReference = (Child)input;
  }
  // Do stuff...
}

因此,我的猜测(我不知道,但如果我错过,请更正我),你在从事非专利工作时所作的这一限制是,因为你的守则不应中断,仅仅是因为你开始在另一个背景下提出,因此,他们不允许你像现在这样写法,尽管在编纂时可能没有任何无效的组合。

这有助于我理解为什么某些事情可以做,某些事情也无法做。 是的,你可以使用“作为”而不是打字,因为如果投稿无效,汇编者只能给你“null”,但如果有可能,可以明确分类编辑检查。 对于通用术语来说,确保它也能在运行时汇编。

改变工厂方法:

public static MyClass<T> Factory<T>(T vd)
    where T: OneType
{
    return new MyClass<T>(vd);
}

然后,你根本不需要开关。

您的实用方法并不反对T。

public static MyClass<T> Factory<T>(T vd) where T: OneType
{
    // ...
}

这一工作应当:

return (MyClass<T>)(object)new SubClass((TwoType)(object)vd);

您能否放弃设计周期? 避免形成一种不灵活工厂方法,而这种方法需要了解<条码>的每个子类别。 与此相类似。

public MyClass<OneType> GetMyClass();

2Type公司负责制造<代码>SubClas 物体,ThreeType,可退回SubTypeThree等。

这里的术语是,你根据物体类型重新开关;这始终是获得子类工作的良好候选人。

<EDIT 1. 例:

(g) ;

public class TwoType: MyClass<TwoType>
{
  public override MyClass<OneType> GetMyClass()
  {
      return new SubClass(this);
  }
}

对我来说,这项工作是:

public class OneType
{

}

public class MyClass<T> where T : OneType
{
    T MyObj
    { get; set; }
    public MyClass(T obj)
    {
    }
    public static MyClass<T> Factory<T>(T vd)
      where T : OneType
    {
        if (vd is TwoType)
        {
            return (MyClass<T>)(object)new SubClass(vd as TwoType);
        }
        return null;
    }

    public string Working
    {
        get { return this.GetType().Name; }
    }

}

public class TwoType : OneType
{

}


public class SubClass : MyClass<TwoType>
{
    public SubClass(TwoType obj)
        : base(obj)
    {

    }
}

我采取的形式是:

        MyClass<TwoType> t = MyClass<TwoType>.Factory<TwoType>(new TwoType());

        MessageBox.Show(t.Working);

EDIT:显然,这并不像上文所述的爱立体观点那样理想。 虽然这一法典在技术上编纂并在一定程度上发挥作用,但你可能希望找到更好的整体解决办法。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...