.net core 里想写一个针对所有数字类型的函数, 该怎么写, 所有类型写一遍, 还是有泛型可用? 还有.net 泛型是不是无法向上转型? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bthulu
V2EX    问与答

.net core 里想写一个针对所有数字类型的函数, 该怎么写, 所有类型写一遍, 还是有泛型可用? 还有.net 泛型是不是无法向上转型?

  •  
  •   bthulu 2022-09-17 21:00:25 +08:00 1817 次点击
    这是一个创建于 1127 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题 1:
    很简单的一个方法, 判断给点数字是不是在另两个数字范围内.

     public static bool Between(int i, int[] range) { return i >= range[0] && i <= range[1]; } 

    但是现在不仅仅是要判断 int, 还可能是 long, float, double.
    这种在 C#里应该怎么做? 下面这样的写法编译报错.

     public static bool Between<T>(T i, T[] range) where T: int, long, float, double { return i >= range[0] && i <= range[1]; } 

    问题 2: 方法里用到个链表, 需要限制链表里必须是动物, 但是可能是猫也可能是狗. 这种应该怎么写?
    下面这样的是无法通过编译的

    List<Animal> list = new List<Cat>(); list = new new List<Dog>(); 
    10 条回复    2022-09-18 16:55:12 +08:00
    hez2010
        1
    hez2010  
       2022-09-17 21:14:19 +08:00   1
    针对数学的泛型是在 C# 11 才引入的,所以需要 .NET 7 ,目前发了 RC 版本。

    第一个问题:

    可以使用 `IComparisonOperators` 作为约束:

    ```csharp
    using System.Numerics;

    static bool Between<T>(T i, T[] range) where T : IComparisonOperators<T, T, bool>
    {
    return i >= range[0] && i <= range[1];
    }
    ```


    第二个问题:

    你直接用 `List<Animal> list = new List<Animal>()` 就行了,然后可以调用 `list.Add(new Dog())` 和 `list.Add(new Cat())` 往里面添加狗或者猫。

    .NET 泛型可以向上或者向下转类型,这个分别叫做协变和逆变,只能在接口上用,例如:

    ```csharp
    void Test1(IFoo1<object> s)
    {
    IFoo1<string> x = s; // ok
    }

    void Test2(IFoo2<string> s)
    {
    IFoo2<object> x = s; // ok
    }

    interface IFoo1<in T> { }
    interface IFoo2<out T> { }
    ```
    bthulu
        2
    bthulu  
    OP
       2022-09-17 22:31:10 +08:00
    @hez2010 @hez2010 第二个问题, 我这里没这么简单.
    实际是从配置文件中读取类似下面这样的
    public class Config {
    public string Farmer {get;set;}
    public List<Dog> Dogs {get;set;}
    public List<Cat> Cats {get;set;}
    }

    然后在另一个方法里动态引用 Dogs 或 Cats
    public void DoSomething(string animalType) {
    Config cOnfig= ReadFromJsonFile();

    // 这个赋值会报错, 无法将 List<Dog>或 List<Cat>赋值给 List<Animal>
    List<Animal> animals = animalType switch {
    "Dog" => config.Dogs,
    "Cat" => config.Cats,
    _ => config.Cats
    }
    foreach(var animal in animals) {
    animal.Dance();
    }
    }
    bthulu
        3
    bthulu  
    OP
       2022-09-17 22:36:22 +08:00
    @hez2010 刚才又试了下, .net core 里是没有 IComparisonOperators 这个类的, 你这个怕不是.net framework4.x 里的吧
    hez2010
        4
    hez2010  
       2022-09-17 23:04:13 +08:00
    @bthulu IComparisonOperators 是 .NET 7 的
    moen
        5
    moen  
       2022-09-17 23:31:47 +08:00
    @bthulu 具体类型是不变的,所以无法赋值。这个例子下必须使用 IReadOnlyList<Animal>
    yor1g
        6
    yor1g  
       2022-09-17 23:44:20 +08:00   1
    这不是都用接口来约束不就行了 何必要具体类或基础类型来做约束... 都是面向对象基础
    beyondex
        7
    beyondex  
       2022-09-18 01:31:18 +08:00 via Android
    1 楼正解
    Magentaize
        8
    Magentaize  
       2022-09-18 08:36:45 +08:00 via iPhone
    List 是 class 不实现协变,只有接口可以实现协变
    bthulu
        9
    bthulu  
    OP
       2022-09-18 10:09:20 +08:00
    @moen 还真可以了. 可为啥不在 IList 上实现协变呢
    moen
        10
    moen  
       2022-09-18 16:55:12 +08:00
    @bthulu IList<T> 的 T 同时出现在参数和返回值里,它就是不变的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana   nbsp; 1611 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 16:22 PVG 00:22 LAX 09:22 JFK 12:22
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86