【问题标题】:c# Activator.CreateInstace how do i cast to generic base type?c# Activator.CreateInstance 我如何转换为泛型基类型?
【发布时间】:2017-10-28 15:41:18
【问题描述】:

我正在尝试使用基于套装、颜色、等级的派生类型的泛型来构建一副纸牌(有许多不同类型的纸牌)。我在如何使用反射创建它们然后将生成的对象转换为基本 PlayingCard 类型 PlayingCard 时遇到问题

    public class Name {}
    public class SpadesName : Name {}

    public class Color {}
    public class BlackColor : Color {}

    public class Rank {}
    public class AceRank : Rank {}

    public class PlayingCard<TName, TColor, TRank>
     where TName: Name, new()
     where TColor: Color, new()
     where TRank: Rank, new()
    {}

    public class DeckOfCards
    {
    public PlayingCard<Name, Color, Rank>[] cards;

    public DeckOfCards() {}

    public void BuildDeckOfCards()
    {
        this.cards = new PlayingCard<Name, Color, Rank>[52];

        Type[] fpcTypeArgs = { typeof(SpadesName), typeof(BlackColor), typeof(AceRank) };
        Type fpcType = typeof(PlayingCard<,,>);
        Type constructable = fpcType.MakeGenericType(fpcTypeArgs);

        // the problem is here.. this will not cast.
        // how do I create an object using reflection and cast it to the generic base type PlayingCard<Name, Color, Rank>
        var fpc = Activator.CreateInstance(constructable);
        this.cards[0] = fpc; 
    }
 }

【问题讨论】:

  • 这是我多年来见过的最严重的仿制药滥用。为什么你会以这种方式使用泛型?只需使用 SuitRank 属性创建一个 Card 类。
  • @InBetween 是的,我知道这些类型的 cmets 会在创纪录的时间内发布。正如帖子所述,我正在尝试使用泛型解决这个问题。这里有一张你看不到的更大的图片。我很清楚这可以具体做到。请尊重发帖的原因。
  • 没有多少运行时反射会改变PlayingCard&lt;Name, Color, Rank&gt;PlayingCard&lt;SpadesName, BlackColor, AceRank&gt; 是不同类型的事实。如果创建后者的实例,则不能将其存储在前者的数组中。您真正追求的可能是也可能不是,但是如果您不想展示那是什么并且不想让其他人在答案中解决这个问题,我看不出有任何方法可以提供有用的答案这个问题。
  • 这里有一张你看不到的大图。那么,首先要这样说,如果你期待误解的话,更是如此。查看 c# 泛型类型差异,在这个主题上一定有无数关于 SO 的问题,所以你会发现阅读这个主题相当容易。长话短说,Bowl&lt;Animal&gt;Bowl&lt;Turtle&gt; 是两种截然不同的类型,只有在非常特定的情况下才能使用一种代替另一种。
  • @InBetween 再次感谢您的另一条未回答的评论。

标签: c# generics reflection casting


【解决方案1】:
using System;

public class Name { }
public class SpadesName : Name { }

public class Color { }
public class BlackColor : Color { }

public class Rank { }
public class AceRank : Rank { }

public interface IPlayingCard<out TName, out TColor, out TRank>
//where TName : Name, new()
//where TColor : Color, new()
//where TRank : Rank, new()
{ }

public class PlayingCard<TName, TColor, TRank> : IPlayingCard<Name, Color, Rank> 
    where TName : Name, new()
    where TColor : Color, new()
    where TRank : Rank, new()
{ }


public class DeckOfCards
{
    public IPlayingCard<Name, Color, Rank>[] cards;

    public DeckOfCards() { }

    public void BuildDeckOfCards()
    {
        this.cards = new IPlayingCard<Name, Color, Rank>[52];

        Type[] fpcTypeArgs = { typeof(SpadesName), typeof(BlackColor), typeof(AceRank) };
        Type fpcType = typeof(PlayingCard<,,>);
        Type constructable = fpcType.MakeGenericType(fpcTypeArgs);

        // the problem is here.. this will not cast.
        // how do I create an object using reflection and cast it to the generic base type PlayingCard<Name, Color, Rank>
        var fpc = Activator.CreateInstance(constructable);
        this.cards[0] = (IPlayingCard<Name, Color, Rank>)fpc;
    }
}

【讨论】:

  • 抱歉,这很糟糕。现在一、二和三是类。您如何比较IPlayingCard&lt;SpadesName, BlackColor, OneRank&gt;IPlayingCard&lt;SpadesName, BlackColor, TwoRank&gt; 以确定哪个更大?你如何确定五张牌是否构成某种序列?二十一点 - 我有一个 SevenRank 和一个 KingRank。我怎么知道我是否应该再拿一张卡?
  • @ScottHannen 使用完全和部分特化方法重载:排名有一个值(取决于游戏),这将允许您创建一个通用的比较器和基于该值的排序器。重载的 CountSuit(card) 方法对每个花色名称都有专门化,并将计算手牌的花色计数并寻找 5 或更多(同花)的花色。基于类型的代码架构是一种方式。
猜你喜欢
  • 2014-07-24
  • 1970-01-01
  • 2015-11-17
  • 2017-09-22
  • 2014-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
相关资源
最近更新 更多