首页 新闻 赞助 找找看

c#:在泛型类中如何访问 约束基类 的子类对象 的独特字段?

0
悬赏园豆:50 [已解决问题] 解决于 2017-05-09 11:53
    public abstract class Animal{}
    public class Dog:Animal{
        public int Legs{ get; set;}
    }
    public class An<T>where T:Animal{
        public  List<T> l = new List<T>();//给v中保存Dog类型数据
        public void Print(){
            foreach (var v in l)
                Console.WriteLine(l.Legs);//怎么访问v中的Legs?
        }
    }

c#
风人的主页 风人 | 初学一级 | 园豆:132
提问于:2017-05-09 11:30
< >
分享
最佳答案
0

你的是T是Animal,animal没有Leg,Leg是Dog的;因此需要判断 v is Dog 然后 (v as Dog).Leg;

除非你t直接是Dog你上面就可以直接通过了。

收获园豆:50
花飘水流兮 | 专家六级 |园豆:13560 | 2017-05-09 11:35

可以可以了,第一次发现还有 v as Dog 这个属性,完美的解决了这段时间一直以来的困惑!!O(∩_∩)O谢谢

        public void Print(){
            foreach (var v in l)
                if (v is Dog) {
                    (v as Dog).Legs = 6;
                    Console.WriteLine ((v as Dog).Legs);
                }
        }

感谢感谢!!我去好好看看这个语法,嘿嘿嘿

 

风人 | 园豆:132 (初学一级) | 2017-05-09 11:43
其他回答(3)
0

给它转型试试?  转型后 看能不能得到legs这个属性

筱浬 | 园豆:601 (小虾三级) | 2017-05-09 11:34

转型不行,父类对象是强转不了子类对象的,2楼方法完美解决,哈哈哈。谢谢解答~~

支持(0) 反对(0) 风人 | 园豆:132 (初学一级) | 2017-05-09 11:45

@风人: 是的 忘记判断了

支持(0) 反对(0) 筱浬 | 园豆:601 (小虾三级) | 2017-05-09 11:51
0

不太好办,你T类型限制在animal上了,变通点的做法是把dog.legs通过委托带进去(带狗腿!?)

void Print(Func<T,object> printQuery)

{

  ...

  Console.WriteLine(printQuery(v));

}

Daniel Cai | 园豆:10424 (专家六级) | 2017-05-09 11:36

这样就是感觉挺麻烦的,如果要用到的数据更多的话就感觉好糟糕--

2楼方法觉得很好,,嘿嘿嘿,谢谢解答~~

支持(0) 反对(0) 风人 | 园豆:132 (初学一级) | 2017-05-09 11:48

@风人: 这个。。。。你泛型这样用的姿势不太对。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2017-05-09 13:48

@Daniel Cai: 是挺别扭--刚学,不太会用。。

支持(0) 反对(0) 风人 | 园豆:132 (初学一级) | 2017-05-09 14:27

@风人: 泛型限制的有点好处就是编译安全性,如果一强转那么就失去了这个保证,而且同时增加了对实现的耦合度。

这里正确姿势是提个接口,接口方法的用途就是返回狗腿鸡毛啥的玩意(看你需求),Print方法继续加泛型限制Print<V>() where V:T,ICountable (ICountable返回狗腿数量)

这样就能在保证安全性的同时保证灵活性。

支持(1) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2017-05-09 18:56

@Daniel Cai: 感谢指导~~

    public class Animal{}
    public interface GetDogColumn{
        int Legs{ get; set;}
    }
    public class Dog:Animal,GetDogColumn{
        public int Legs{ get; set;}
    }

    public class An<T>where T:Animal{
        public  List<T> l = new List<T>();//给v中保存Dog类型数据

        public void Print(){
            foreach (var v in l) {
                Dog _dog = v as Dog;
                if (_dog != null) {
                    _dog.Legs = 6;
                    Console.WriteLine (_dog.Legs);
                }
            }
        }
        public void Print<V>()where V:T,GetDogColumn{//Print方法继续加泛型限制
            foreach (V v in l) {
                v.Legs = 4;
                Console.WriteLine (v.Legs);
            }
        }
    }

是这样写吗?我试了下,可以实现想要的功能--

那就是用这个方法就是比用 as 强转更好吗?

支持(0) 反对(0) 风人 | 园豆:132 (初学一级) | 2017-05-09 19:24

@风人: 恩

ps

1..net中约定俗成接口以大写I卡头,一般接口命名能表达的意思为可以干什么(Ixxxable),仅做标识的接口可以不这样干,比如IRequireSessionState等。

2.单纯针对你现在的需求当然这样写属于过度设计,但当功能复杂,对象关系较多后这样写的好处就会体现出来了。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2017-05-09 19:30

@Daniel Cai: 嗯嗯嗯,刚才又试了试访问Animal两个子类的特有的属性,更加理解了~~

非常感谢你的指导!O(∩_∩)O谢谢

支持(0) 反对(0) 风人 | 园豆:132 (初学一级) | 2017-05-09 20:10
0

2l的方法是好.但是你的问题就是错的.

既然泛型了.就不可能还限定子类.限定子类了.还泛型干嘛.

吴瑞祥 | 园豆:29449 (高人七级) | 2017-05-09 13:08

这个确实是,就是现在学到这,觉得这样定义一个容器类挺好的:

用一个泛型数组来保存Animal类各种子类的数据,就是可以定义一个An<Dog>对象来保存n个Dog类对象,也可以定义一个An<Pig>来保存n个Pig对象(Pig也是Animal的子类),因为Dog和Pig都是Animal子类,所以用泛型约束成Animal基类约束。并且在这个泛型容器类里对这个数组进行操作。

支持(0) 反对(0) 风人 | 园豆:132 (初学一级) | 2017-05-09 14:26
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册