4 ms·
Both types `List<T>`and `T[]` are `object` aka Rust's `Box<T>`. There's little profit most of the time for using `ToArray()` over `ToList()`, and in places wher
by neonsunset 4y ago
Both types `List<T>`and `T[]` are `object` aka Rust's `Box<T>`. There's little profit most of the time for using `ToArray()` over `ToList()`, and in places where it does matter, there is a high chance that using `IEnumerable<T>` is bad idea due to its performance overhead.
I believe, the best implementation of `IEnumerable<T>` we have today are Rust's iterator types which provide the same functionality but with performance comparable or even better than manually written imperative loops.
- WorldMaker 4y agoThat's not entirely true. .NET's object is very different from Box<T> from my understanding. My rust understanding is rusty (not sorry), but .NET's object is much closer to &mut than Box<T> as it is the top type in the type system. There's the reference type/value type split "below" object. Reference types like `List<T>` are always heap allocated (like Box<T>), but value types like T[] might not be and may be stack allocated. Small enough arrays can reify entirely in stack space (function locals) rather than heap space and with some uses of ToArray() the JIT compiler is smart enough to make the right call, whereas List<T> always creates heap allocations and ToList() unavoidably churns at least Gen 0 of the garbage collector that tiny bit more. IEnumerable<T> doesn't give you enough information of the implementation details to know if that interface is implemented as a reference type or value type. Some implementations of IEnumerable<T> are non-heap allocated value types (structs)! Often many implementations in performance critical areas of the framework are structs.
- neonsunset 4y agoUnfortunately, while I would love JIT to do such kind of optimizations, this is completely not how it works today. First and foremost, '&mut' in Rust is a mutable reference. The C# alternative is just 'ref'. Both point to specific addresses. 'Box<T>' OTOH is a handle for a struct allocated on a heap, just like C#'s one is implementation-wise (except in C# they are further managed by runtime but that's besides the point). Now regarding the arrays - 'T[]' is strictly object withouts ifs and buts. There is no "short array" optimisation that would substitute array type with stack-allocated inline buffer. If you want this, you have to write it manually. See: https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.Icu.cs#L46 https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6b... The last but not least, if the method signature accepts an argument by its interface type e.g. 'HandleEnumerable<T>(IEnumerable<T> values)', then the IEnumerable-implementing struct will be boxed before method can be called. C#/.NET doesn't do full generic monomorphization like Rust. Instead, for class-type generics a common '_Canon' method body will be JITted which will also implicitly accept generic-type arguments to correctly dispatch on an actual <T> of the method. OTOH, for structs, all method calls will be fully monomorphized per each struct type. This means that you can avoid struct boxing when dispatching by interface by rewriting method signature to 'HandleEnumerable<T, TEnumerable>(TEnumerable values) where TEnumerable : IEnumerable<T>'. In this case, unless you cast your struct to an interface type explicitly beforehand, the struct will not be boxed. For the sake of simplicity, this explanation scope doesn't include advanced optimisations done by Tier-1 JIT compilation such as guarded de-virtualization, more aggressive inlining that can potentially elide boxing, etc.
- WorldMaker 4y agoAgain, I still believe you are confusing lower-case CLR `object` (top-type) and upper-case BCL `System.Object` (root-type of "reference types"/"heap types" and below the top-type; they are confusingly named to allow for some abstractions where considering them the same thing makes it easier to reason with, but they are different concerns). Value types in stack space (function locals/small scoped variables) that fit entirely in stack space (size restrictions; "short arrays") never get "boxed" to the heap. `stackalloc` is an important need to restrict such types to the stack, because things like Span<T> require stack types and stack types only, but the general JIT rules apply that value types that don't leave stack scopes often are never "boxed" to the heap, including "short arrays" in function local scopes. (With the complicating caveat that things like async/await change what "function local" means and will increase boxing as things move to async state closures.)
- neonsunset 4y agoYou are free to believe this but if you want me to believe you, please provide official spec or code that says it works that way today. Because making your statements sound reasonable doesn't magically make them true - the truth is far removed from your statements, sorry for putting it bluntly. JIT never did proper escape analysis for object stack allocation except for the small proposal prototype implementation which the runtime team decided to put away for better times: https://github.com/dotnet/runtime/issues/11192 https://github.com/dotnet/runtime/issues/11192 It is never enabled and will not work the way you expect it to even if you try. Huh, now that I think about it, this account might be posting messages generated by GPT-3 and I'm just wasting time.
- WorldMaker 4y agoThe fundamentals of Value Types versus Reference Types: https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/data-types/value-types-and-reference-types https://docs.microsoft.com/en-us/dotnet/visual-basic/program... What you linked is an issue regarding storing Reference Types (classes) in stack space. Again, there is a difference in .NET between a Reference Type and Value Type, and this is a fundamental dichotomy going back to the earliest days of .NET. I don't appreciate the ad hominem attack and suggest that you google any further follow ups yourself.