范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

用了这么多年的泛型,你对它到底有多了解?

  现代程序员写代码没有人敢说自己没用过泛型,这个泛型模板T可以被任何你想要的类型替代,确实很魔法很神奇,很多人也习以为常了,但就是这么有趣的泛型T底层到底是怎么帮你实现的,不知道有多少人清楚底层玩法,这篇我就试着来分享一下,不一定全对哈…一:没有泛型前
  现在的netcore 3.1和最新的.netframework8早已经没有当初那个被人诟病的ArrayList了,但很巧这玩意不得不说,因为它决定了C#团队痛改前非,抛弃过往重新上路,上一段ArrayList案例代码。    public class ArrayList     {         private object[] items;          private int index = 0;          public ArrayList()         {             items = new object[10];         }          public void Add(object item)         {             items[index++] = item;         }     }
  上面这段代码,为了保证在Add中可以塞入各种类型 eg: int,double,class, 就想到了一个绝招用祖宗类object接收,这就引入了两大问题,装箱拆箱和类型安全。1. 装箱拆箱
  这个很好理解,因为你使用了祖宗类,所以当你 Add 的时候塞入的是值类型的话,自然就有装箱操作,比如下面代码:            ArrayList arrayList = new ArrayList();             arrayList.Add(3);  占用更大的空间
  这个问题我准备用windbg看一下,相信大家知道一个int类型占用4个字节,那装箱到堆上是几个字节呢,好奇吧。
  原始代码和IL代码如下:        public static void Main(string[] args)         {             var num = 10;             var obj = (object)num;             Console.Read();         }      IL_0000: nop 	IL_0001: ldc.i4.s 10 	IL_0003: stloc.0 	IL_0004: ldloc.0 	IL_0005: box [mscorlib]System.Int32 	IL_000a: stloc.1 	IL_000b: call int32 [mscorlib]System.Console::Read() 	IL_0010: pop 	IL_0011: ret
  可以清楚的看到IL_0005 中有一个box指令,装箱没有问题,然后抓一下dump文件。
  ~0s -> !clrstack -l -> !do 0x0000018300002d48 0:000> ~0s ntdll!ZwReadFile+0x14: 00007ff9`fc7baa64 c3              ret 0:000> !clrstack -l OS Thread Id: 0xfc (0)         Child SP               IP Call Site 0000002c397fedf0 00007ff985c808f3 ConsoleApp2.Program.Main(System.String[]) [C:dreamCsharpConsoleApp1ConsoleApp2Program.cs @ 28]     LOCALS:         0x0000002c397fee2c = 0x000000000000000a         0x0000002c397fee20 = 0x0000018300002d48  0000002c397ff038 00007ff9e51b6c93 [GCFrame: 0000002c397ff038]  0:000> !do 0x0000018300002d48 Name:        System.Int32 MethodTable: 00007ff9e33285a0 EEClass:     00007ff9e34958a8 Size:        24(0x18) bytes File:        C:WINDOWSMicrosoft.NetassemblyGAC_64mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dll Fields:               MT    Field   Offset                 Type VT     Attr            Value Name 00007ff9e33285a0  40005a0        8         System.Int32  1 instance               10 m_value
  倒数第5行 Size: 24(0x18) bytes, 可以清楚的看到是24字节。 为什么是24个字节,8(同步块指针) + 8(方法表指针) + 4(对象大小)=20,但因为是x64位,内存是按8对齐,也就是要按8的倍数计算,所以占用是 8+8+8 =24 字节,原来只有4字节的大小因为装箱已被爆到24字节,如果是10000个值类型的装箱那空间占用是不是挺可怕的? 栈到堆的装箱搬运到运输到售后到无害化处理都需要付出重大的人力和机器成本2. 类型不安全
  很简单,因为是祖宗类型object,所以无法避免程序员使用乱七八糟的类型,当然这可能是无意的,但是编译器确无法规避,代码如下:             ArrayList arrayList = new ArrayList();             arrayList.Add(3);             arrayList.Add(new Action((num) => { }));             arrayList.Add(new object());
  面对这两大尴尬的问题,C#团队决定重新设计一个类型,实现一定终身,这就有了泛型。二:泛型的出现1. 救世主
  首先可以明确的说,泛型就是为了解决这两个问题而生的,你可以在底层提供的List中使用List,List…等等你看得上的类型,而这种技术的底层实现原理才是本篇关注的重点。         public static void Main(string[] args)         {             List list1 = new List();             List list3 = new List();             ...         }  三:泛型原理探究
  这个问题的探索其实就是 List -> List在何处实现了 T -> int 的替换,反观java,它的泛型实现其实在底层还是用object来替换的,C#肯定不是这么做的,不然也没这篇文章啦,要知道在哪个阶段被替换了,你起码要知道C#代码编译的几个阶段,为了理解方便,我画一张图吧。
  流程大家也看到了,要么在MSIL中被替换,要么在JIT编译中被替换…         public static void Main(string[] args)         {             List list1 = new List();             List list2 = new List();             List list3 = new List();             List list4 = new List();              Console.ReadLine();         }  1. 在第一阶段探究
  因为第一阶段是MSIL代码,所以用ILSpy看一下中间代码即可。		IL_0000: nop 		IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1::.ctor() 		IL_0006: stloc.0 		IL_0007: newobj instance void class [mscorlib]System.Collections.Generic.List`1::.ctor() 		IL_000c: stloc.1 		IL_000d: newobj instance void class [mscorlib]System.Collections.Generic.List`1::.ctor() 		IL_0012: stloc.2 		IL_0013: newobj instance void class [mscorlib]System.Collections.Generic.List`1::.ctor() 		IL_0018: stloc.3 		IL_0019: call string [mscorlib]System.Console::ReadLine() 		IL_001e: pop 		IL_001f: ret  .class public auto ansi serializable beforefieldinit System.Collections.Generic.List`1 	extends System.Object 	implements class System.Collections.Generic.IList`1, 	           class System.Collections.Generic.ICollection`1, 	           class System.Collections.Generic.IEnumerable`1, 	           System.Collections.IEnumerable, 	           System.Collections.IList, 	           System.Collections.ICollection, 	           class System.Collections.Generic.IReadOnlyList`1, 	           class System.Collections.Generic.IReadOnlyCollection`1
  从上面的IL代码中可以看到,最终的类定义还是 System.Collections.Generic.List1,说明在中间代码阶段还是没有实现 T -> int 的替换。2. 在第二阶段探究
  想看到JIT编译后的代码,这个说难也不难,其实每个对象头上都有一个方法表指针,而这个指针指向的就是方法表,方法表中有该类型的所有最终生成方法,如果不好理解,我就画个图。
  !dumpheap -stat 寻找托管堆上的四个List对象。 0:000> !dumpheap -stat Statistics:               MT    Count    TotalSize Class Name 00007ff9e3314320        1           32 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle 00007ff9e339b4b8        1           40 System.Collections.Generic.List`1[[System.Double, mscorlib]] 00007ff9e333a068        1           40 System.Collections.Generic.List`1[[System.Int32, mscorlib]] 00007ff9e3330d58        1           40 System.Collections.Generic.List`1[[System.String, mscorlib]] 00007ff9e3314a58        1           40 System.IO.Stream+NullStream 00007ff9e3314510        1           40 Microsoft.Win32.Win32Native+InputRecord 00007ff9e3314218        1           40 System.Text.InternalEncoderBestFitFallback 00007ff985b442c0        1           40 System.Collections.Generic.List`1[[System.Int32[], mscorlib]] 00007ff9e338fd28        1           48 System.Text.DBCSCodePageEncoding+DBCSDecoder 00007ff9e3325ef0        1           48 System.SharedStatics
  可以看到从托管堆中找到了4个list对象,现在我就挑一个最简单的 System.Collections.Generic.List1[[System.Int32, mscorlib]] ,前面的 00007ff9e333a068 就是方法表地址。
  !dumpmt -md 00007ff9e333a068 0:000> !dumpmt -md 00007ff9e333a068 EEClass:         00007ff9e349b008 Module:          00007ff9e3301000 Name:            System.Collections.Generic.List`1[[System.Int32, mscorlib]] mdToken:         00000000020004af File:            C:WINDOWSMicrosoft.NetassemblyGAC_64mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dll BaseSize:        0x28 ComponentSize:   0x0 Slots in VTable: 77 Number of IFaces in IFaceMap: 8 -------------------------------------- MethodDesc Table            Entry       MethodDesc    JIT Name 00007ff9e3882450 00007ff9e3308de8 PreJIT System.Object.ToString() 00007ff9e389cc60 00007ff9e34cb9b0 PreJIT System.Object.Equals(System.Object) 00007ff9e3882090 00007ff9e34cb9d8 PreJIT System.Object.GetHashCode() 00007ff9e387f420 00007ff9e34cb9e0 PreJIT System.Object.Finalize() 00007ff9e38a3650 00007ff9e34dc6e8 PreJIT System.Collections.Generic.List`1[[System.Int32, mscorlib]].Add(Int32) 00007ff9e4202dc0 00007ff9e34dc7f8 PreJIT System.Collections.Generic.List`1[[System.Int32, mscorlib]].Insert(Int32, Int32)
  上面方法表中的方法过多,我做了一下删减,可以清楚的看到,此时Add方法已经接受(Int32)类型的数据了,说明在JIT编译之后,终于实现了 T -> int 的替换,然后再把 List 打出来看一下。 0:000> !dumpmt -md 00007ff9e339b4b8 MethodDesc Table            Entry       MethodDesc    JIT Name 00007ff9e3882450 00007ff9e3308de8 PreJIT System.Object.ToString() 00007ff9e389cc60 00007ff9e34cb9b0 PreJIT System.Object.Equals(System.Object) 00007ff9e3882090 00007ff9e34cb9d8 PreJIT System.Object.GetHashCode() 00007ff9e387f420 00007ff9e34cb9e0 PreJIT System.Object.Finalize() 00007ff9e4428730 00007ff9e34e4170 PreJIT System.Collections.Generic.List`1[[System.Double, mscorlib]].Add(Double) 00007ff9e3867a00 00007ff9e34e4280 PreJIT System.Collections.Generic.List`1[[System.Double, mscorlib]].Insert(Int32, Double)
  上面看的都是值类型,接下来再看一下如果 T 是引用类型会是怎么样呢? 0:000> !dumpmt -md 00007ff9e3330d58 MethodDesc Table            Entry       MethodDesc    JIT Name 00007ff9e3890060 00007ff9e34eb058 PreJIT System.Collections.Generic.List`1[[System.__Canon, mscorlib]].Add(System.__Canon)  0:000> !dumpmt -md 00007ff985b442c0 MethodDesc Table            Entry       MethodDesc    JIT Name 00007ff9e3890060 00007ff9e34eb058 PreJIT System.Collections.Generic.List`1[[System.__Canon, mscorlib]].Add(System.__Canon)
  可以看到当是List 和 List 的时候,JIT使用了 System.__Canon 这么一个类型作为替代,有可能人家是摄影爱好者吧,为什么用__Canon替代引用类型,这是因为它想让能共享代码区域的方法都共享来节省空间和内存吧,不信的话可以看看它们的Entry列都是同一个内存地址:00007ff9e3890060, 打印出来就是这么一段汇编。 0:000> !u 00007ff9e3890060 preJIT generated code System.Collections.Generic.List`1[[System.__Canon, mscorlib]].Add(System.__Canon) Begin 00007ff9e3890060, size 4a >>> 00007ff9`e3890060 57              push    rdi 00007ff9`e3890061 56              push    rsi 00007ff9`e3890062 4883ec28        sub     rsp,28h 00007ff9`e3890066 488bf1          mov     rsi,rcx 00007ff9`e3890069 488bfa          mov     rdi,rdx 00007ff9`e389006c 8b4e18          mov     ecx,dword ptr [rsi+18h] 00007ff9`e389006f 488b5608        mov     rdx,qword ptr [rsi+8] 00007ff9`e3890073 3b4a08          cmp     ecx,dword ptr [rdx+8] 00007ff9`e3890076 7422            je      mscorlib_ni+0x59009a (00007ff9`e389009a) 00007ff9`e3890078 488b4e08        mov     rcx,qword ptr [rsi+8] 00007ff9`e389007c 8b5618          mov     edx,dword ptr [rsi+18h] 00007ff9`e389007f 448d4201        lea     r8d,[rdx+1] 00007ff9`e3890083 44894618        mov     dword ptr [rsi+18h],r8d 00007ff9`e3890087 4c8bc7          mov     r8,rdi 00007ff9`e389008a ff152088faff    call    qword ptr [mscorlib_ni+0x5388b0 (00007ff9`e38388b0)] (JitHelp: CORINFO_HELP_ARRADDR_ST) 00007ff9`e3890090 ff461c          inc     dword ptr [rsi+1Ch] 00007ff9`e3890093 4883c428        add     rsp,28h 00007ff9`e3890097 5e              pop     rsi 00007ff9`e3890098 5f              pop     rdi 00007ff9`e3890099 c3              ret 00007ff9`e389009a 8b5618          mov     edx,dword ptr [rsi+18h] 00007ff9`e389009d ffc2            inc     edx 00007ff9`e389009f 488bce          mov     rcx,rsi 00007ff9`e38900a2 90              nop 00007ff9`e38900a3 e8c877feff      call    mscorlib_ni+0x577870 (00007ff9`e3877870) (System.Collections.Generic.List`1[[System.__Canon, mscorlib]].EnsureCapacity(Int32), mdToken: 00000000060039e5) 00007ff9`e38900a8 ebce            jmp     mscorlib_ni+0x590078 (00007ff9`e3890078)
  然后再回过头看List 和 List ,从Entry列中看确实不是一个地址,说明List 和 List是两个完全不一样的Add方法,看得懂汇编的可以自己看一下哈…MethodDesc Table            Entry       MethodDesc    JIT Name 00007ff9e38a3650 00007ff9e34dc6e8 PreJIT System.Collections.Generic.List`1[[System.Int32, mscorlib]].Add(Int32) 00007ff9e4428730 00007ff9e34e4170 PreJIT System.Collections.Generic.List`1[[System.Double, mscorlib]].Add(Double)  0:000> !u 00007ff9e38a3650 preJIT generated code System.Collections.Generic.List`1[[System.Int32, mscorlib]].Add(Int32) Begin 00007ff9e38a3650, size 50 >>> 00007ff9`e38a3650 57              push    rdi 00007ff9`e38a3651 56              push    rsi 00007ff9`e38a3652 4883ec28        sub     rsp,28h 00007ff9`e38a3656 488bf1          mov     rsi,rcx 00007ff9`e38a3659 8bfa            mov     edi,edx 00007ff9`e38a365b 8b5618          mov     edx,dword ptr [rsi+18h] 00007ff9`e38a365e 488b4e08        mov     rcx,qword ptr [rsi+8] 00007ff9`e38a3662 3b5108          cmp     edx,dword ptr [rcx+8] 00007ff9`e38a3665 7423            je      mscorlib_ni+0x5a368a (00007ff9`e38a368a) 00007ff9`e38a3667 488b5608        mov     rdx,qword ptr [rsi+8] 00007ff9`e38a366b 8b4e18          mov     ecx,dword ptr [rsi+18h] 00007ff9`e38a366e 8d4101          lea     eax,[rcx+1] 00007ff9`e38a3671 894618          mov     dword ptr [rsi+18h],eax 00007ff9`e38a3674 3b4a08          cmp     ecx,dword ptr [rdx+8] 00007ff9`e38a3677 7321            jae     mscorlib_ni+0x5a369a (00007ff9`e38a369a) 00007ff9`e38a3679 4863c9          movsxd  rcx,ecx 00007ff9`e38a367c 897c8a10        mov     dword ptr [rdx+rcx*4+10h],edi 00007ff9`e38a3680 ff461c          inc     dword ptr [rsi+1Ch] 00007ff9`e38a3683 4883c428        add     rsp,28h 00007ff9`e38a3687 5e              pop     rsi 00007ff9`e38a3688 5f              pop     rdi 00007ff9`e38a3689 c3              ret 00007ff9`e38a368a 8b5618          mov     edx,dword ptr [rsi+18h] 00007ff9`e38a368d ffc2            inc     edx 00007ff9`e38a368f 488bce          mov     rcx,rsi 00007ff9`e38a3692 90              nop 00007ff9`e38a3693 e8a8e60700      call    mscorlib_ni+0x621d40 (00007ff9`e3921d40) (System.Collections.Generic.List`1[[System.Int32, mscorlib]].EnsureCapacity(Int32), mdToken: 00000000060039e5) 00007ff9`e38a3698 ebcd            jmp     mscorlib_ni+0x5a3667 (00007ff9`e38a3667) 00007ff9`e38a369a e8bf60f9ff      call    mscorlib_ni+0x53975e (00007ff9`e383975e) (mscorlib_ni) 00007ff9`e38a369f cc              int     3   0:000> !u 00007ff9e4428730 preJIT generated code System.Collections.Generic.List`1[[System.Double, mscorlib]].Add(Double) Begin 00007ff9e4428730, size 5a >>> 00007ff9`e4428730 56              push    rsi 00007ff9`e4428731 4883ec20        sub     rsp,20h 00007ff9`e4428735 488bf1          mov     rsi,rcx 00007ff9`e4428738 8b5618          mov     edx,dword ptr [rsi+18h] 00007ff9`e442873b 488b4e08        mov     rcx,qword ptr [rsi+8] 00007ff9`e442873f 3b5108          cmp     edx,dword ptr [rcx+8] 00007ff9`e4428742 7424            je      mscorlib_ni+0x1128768 (00007ff9`e4428768) 00007ff9`e4428744 488b5608        mov     rdx,qword ptr [rsi+8] 00007ff9`e4428748 8b4e18          mov     ecx,dword ptr [rsi+18h] 00007ff9`e442874b 8d4101          lea     eax,[rcx+1] 00007ff9`e442874e 894618          mov     dword ptr [rsi+18h],eax 00007ff9`e4428751 3b4a08          cmp     ecx,dword ptr [rdx+8] 00007ff9`e4428754 732e            jae     mscorlib_ni+0x1128784 (00007ff9`e4428784) 00007ff9`e4428756 4863c9          movsxd  rcx,ecx 00007ff9`e4428759 f20f114cca10    movsd   mmword ptr [rdx+rcx*8+10h],xmm1 00007ff9`e442875f ff461c          inc     dword ptr [rsi+1Ch] 00007ff9`e4428762 4883c420        add     rsp,20h 00007ff9`e4428766 5e              pop     rsi 00007ff9`e4428767 c3              ret 00007ff9`e4428768 f20f114c2438    movsd   mmword ptr [rsp+38h],xmm1 00007ff9`e442876e 8b5618          mov     edx,dword ptr [rsi+18h] 00007ff9`e4428771 ffc2            inc     edx 00007ff9`e4428773 488bce          mov     rcx,rsi 00007ff9`e4428776 90              nop 00007ff9`e4428777 e854fbffff      call    mscorlib_ni+0x11282d0 (00007ff9`e44282d0) (System.Collections.Generic.List`1[[System.Double, mscorlib]].EnsureCapacity(Int32), mdToken: 00000000060039e5) 00007ff9`e442877c f20f104c2438    movsd   xmm1,mmword ptr [rsp+38h] 00007ff9`e4428782 ebc0            jmp     mscorlib_ni+0x1128744 (00007ff9`e4428744) 00007ff9`e4428784 e8d50f41ff      call    mscorlib_ni+0x53975e (00007ff9`e383975e) (mscorlib_ni) 00007ff9`e4428789 cc              int     3
  可能你有点蒙,我画一张图吧。
  四: 总结
  泛型T真正的被代替是在 JIT编译时才实现的,四个List 会生成四个具有相应具体类型的类对象,所以就不存在拆箱和装箱的问题,而类型的限定visualstudio编译器工具提前就帮我们约束好啦。

微信充值话费扣款成功却没到账是怎么回事?微信充话费,好像不支付充联通的号码。上次我给家里人充的就不能到帐,后面款返回到我的微信零钱了。但是用微信充移动的很快就到了。后面我用淘宝充联通才成功,不过我没试过用支付充联通号码的电脑硬件什么时候才降价啊?现在就连显示器都涨价了?电脑配件大部由于芯片缺货,现在降价很难哦,cpu的价格很难降下来,一是整体缺货,而是有黄牛在炒作。内存的价格就跌了,因为确实很缺需求。ssd的需求与价格也显疲软,行情一片惨淡。中端华为和比亚迪合作能不能超越特斯拉?在电动汽车行业超越特斯拉有点难,几乎没有可能性。即使华为和比亚迪合作也很难。比亚迪有着制造电池的优势,但是与特斯拉和松下合作的电池性能并不明显。华为虽有强大的5G技术,在未来自动驾有人给你误充5000话费,要你还现金,你怎么办?我肯定不会还的让他去找警察告我我无条件配合警察以及运营商首先5000话费在我看来只需要4000多就能充值了其次5000块钱我拿去存小银行拿45的利率一个月就18的利息了我一个月话费618持币3000元,购买什么手机好?感谢您的阅读!618,持币3000元,购买什么手机好呢一直以来,我们都认为一款手机的好坏一定是多种因素共同作用的结果。而在3000元左右,实际上它的价格已经非常具有优势了,怎么选择想买部性能强影像效果又好的手机,五千左右有推荐吗?感谢您的阅读!想买部性能强影像效果又好的手机,五千左右有推荐吗?影像能力实际上对于很多人来说似乎已经变得非常的重要了。我们在选择一款手机的时候,特别是一些影像能力强的手机的时候,确在加密市场暴跌3000亿美元后,狗狗币卷土重来,马斯克能量有多大本周五,在亿万富翁埃隆马斯克的支持下,以及加密货币交易所Coinbase宣布即将上架狗狗币(Dogecoin)之后,狗狗币的价格今天飙升了近30。上周末,由于受到马斯克将在周六夜现涨疯了!狗狗币开发人员透露从2019年起就一直在与马斯克合作狗狗币暴涨55Coinbase将很快增加对狗狗币的支持FX168财经报社(北美)讯周五(5月14日),狗狗币开发人员尼克尔在采访中表示,他们从2019年起就一直在与马斯克合作,让这种加密货币成为比特币更便宜更环保的替代品。据估计,狗狗都喷三缸是原罪,怎么理想ONE成了年度销量冠军?如果用一句话来形容2020年的理想,那闷声发大财肯定是最适合了。2020年理想ONE一年终端销售量为33457辆,击败蔚来成为了2020年度的新能源SUV销量冠军,要知道理想只有理华为确定今年鸿蒙生态目标适配APP超300个近日,据知名数码博主爆料,6月起将会有一大批预装鸿蒙OS的设备登场。同时,华为2021年的目标为至少1016市场份额年底前完成2亿台推送超3亿装机量超300个适配App。这里最值得如果实体行业都关闭了,只剩下电商,是进步还是倒退?如果实体行业都关闭了,只剩下电商,是进步还是倒退?电商的出现,给人们提供了一种全新的购物方式。可以免去实体购物路程的烦恼,只需要在电脑平板手机端点击几下,心仪的商品就会有快递小哥为
Python画圣诞树,这波操作让我女友非常开心文章目录1。方块圣诞树2。线条圣诞树3。豪华圣诞树这篇文章主要介绍了使用Python画了一棵圣诞树的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考iPhone14将迎来4个升级,没换新机的果粉,这次可能等对了今年,苹果没让人失望!9月份发布的四款iPhone13,除了在口碑上表现不错,在市场销量方面也有着比较突出的成绩。尤其是iPhone13iPhone13Pro,受到很多人的认可。此iPhone14Pro或将配备4800万像素主摄,后年还有潜望式长焦镜头根据gsmarena的消息,苹果采用1,200万像素感光元件已经有10年时间了,尽管传感器本身并不是祖传的,但像素数量始终没有突破。而分析师郭明錤这表示这个情况将在iPhone14后端编程Python3调试测试和性能剖析(下)单元测试(UnitTesting)为程序编写测试如果做的到位有助于减少bug的出现,并可以提高我们对程序按预期目标运行的信心。通常,测试并不能保证正确性,因为对大多数程序而言,可能python自带性能强悍的标准库itertools可迭代对象就像密闭容器里的水,有货倒不出itertools是python内置的标准模块,提供了很多简洁又高效的专用功能,使用得当能够极大的简化代码行数,同时所有方法都是实现了生成器电动汽车百公里电耗排行榜,最低与最高电耗相差达到3倍随着电动汽车的普及,各大厂家不仅在电池设计上开始竞争,在能耗方面也是投入更多的研发资金,就像燃油车中的涡轮增压化,降低油耗,电动车近些年能耗也逐渐降低,那么你知道目前市面上百公里电国产巨头的反击来了,美媒最害怕的事将要发生,苹果如何应对?虽然你这个问题问的无厘头,我还是假设你这个问题是在说小米OV和腾讯百度联手的那个金标联盟吧?或者你说的是鸿蒙?从我的角度来看,这个金标联盟的出发点还真不是想要打败苹果,而是一个抱团跨境支付独角兽乒乓智能完成支付牌照股权工商变更,创业板上市进程又近一步?记者苗艺伟天眼查数据显示,近日,上海伊千网络信息技术有限公司发生股权变更,唯一股东中民未来控股集团退出,新增的杭州乒乓智能技术有限公司,持有上海伊千100股权。公开信息显示,上海伊两部门加快新能源汽车推广应用,加快充电桩换电站等配套设施建设北京商报讯(记者陶凤吕银玲)12月14日,国家发改委工业和信息化部发布关于振作工业经济运行推动工业高质量发展的实施方案的通知(以下简称通知),通知提出,释放重点领域消费潜力。加快新华为亲自打造,全球第一颗云卫星升空,任正非说到做到一导读随着科技的不断发展,信息如洪流般涌来,早在2012年,任正非就已经预见了信息洪流爆发后的威力,面对信息洪流的冲击,任正非早有应对,一方面发展自己的手机品牌终端,从而在智能入口瓜子二手车要变淘宝?文财经无忌,作者萧田沉寂许久的二手车市场再次泛起涟漪。全国好车线上选,送车上门试七天,满意再过户,不满意退全款!瓜子二手车,二手车新买法,新买法!。自今年9月罗永浩官宣代言瓜子二手