6 ms·
This (somewhat) complicated process is also why generics can be fully reified in the CLR.
by bigdubs 9y ago
This (somewhat) complicated process is also why generics can be fully reified in the CLR.
- matthewwarren 9y agoThat's a good point, I'd not thought about it like that. So you're saying that unless you load types step-by-step, you can't have fully reified generics types, because of circular references/dependencies, is that the reason?
- kevingadd 9y agoHaving implemented a large subset of this stuff for my own .NET runtime, you absolutely cannot implement the fully reified generics without loading in stages like this. The circular dependencies can get extremely tangled.
- matthewwarren 9y agoThanks for the info > Having implemented a large subset of this stuff for my own .NET runtime Interesting, which runtime was this? Is it the source available anywhere, I'd love to have a look if it was?
- kevingadd 9y agohttps://github.com/sq/JSIL https://github.com/sq/JSIL
- bsaul 9y agoAre there any benchmark of the cost in terms of performance paid by this process compared to other methods in other languages ? I suppose this happens only at load time, but i wonder if that doesn't have other impact elsewhere during the execution.
- matthewwarren 9y agoI'm pretty sure this process only has an impact during startup and even then I don't know if it's that expensive to load Types like this, but I agree, it would be interesting to measure it compared to a similar run-time (say Java)
- simooooo 9y agoIf reflection is being monitored closely etc then it must have some impact. Probably tiny
- matthewwarren 9y agoReflection has a whole load of other overheads (see http://mattwarren.org/2016/12/14/Why-is-Reflection-slow/ http://mattwarren.org/2016/12/14/Why-is-Reflection-slow/ for some info) so I doubt that actually loading a Type is high up the list of time-spent, but I've never actually measured it.
- NicoJuicy 9y agoI love generics! Simplifies all my api creations deeply, huge re-use of code and very flexible implementations. Eg. An API to a IoT cloud that lets user define their own type. The payload that i fetch is <T> so users can define their own type. Another one is an api where i take a generic approach, so my only code that i write ( for every "class" / " model" ) is: //every endpoint does a complete crud + jsonpatch + batch, also, all methods can be overridden to customize code. This is the code i need to write every time :p https://pastebin.com/fp8MtpBu https://pastebin.com/fp8MtpBu Note to myselve: extend the implementation to support expressions ( odata ) in the url ( similar to sql on top of an API through changing url parameters) and return the dto as response. :)
- lloydjatkinson 9y agoVery similar to something I'm working on. Except in my case I have an interface that the consumers implement to be able to talk to their service/database/whatever. It's designed for time series data (e.g., cpu usage, room temperature, that kind of thing). It's meant to only allow for numeric values and strings. But because there is no base type or interface for numeric types I unfortunately can't do something like: public Result WriteValue<T>(T value) where T : INumeric/Numeric { } https://stackoverflow.com/questions/32664/is-there-a-constraint-that-restricts-my-generic-method-to-numeric-types https://stackoverflow.com/questions/32664/is-there-a-constra... :( So instead the interface has an identical method for ints, doubles, floats, decimals, strings...
- apk-d 9y agoMy favorite taunt from the .NET team: according to the .NET Reference Source, built-in numeric types implement an IArithmetic<T> interface... And then they comment it out. http://referencesource.microsoft.com/#mscorlib/system/double.cs,1a65cbdb09544ba1 http://referencesource.microsoft.com/#mscorlib/system/double...
- louthy 9y agoHere's an ad-hoc polymorphic way of dealing with numeric types in C# without the boxing that would be caused by using an IArithmetic interface: public interface Num<A> { A Add(A x, A y); A Subtract(A x, A y); A Multiply(A x, A y); A Divide(A x, A y); A FromInteger(int value); } public struct NumInt : Num<int> { public int Add(int x, int y) => x + y; public int Subtract(int x, int y) => x - y; public int Multiply(int x, int y) => x * y; public int Divide(int x, int y) => x / y; public int FromInteger(int value) => value; } public struct NumDouble : Num<double> { public double Add(double x, double y) => x + y; public double Subtract(double x, double y) => x - y; public double Multiply(double x, double y) => x * y; public double Divide(double x, double y) => x / y; public double FromInteger(int value) => (double)value; } public struct NumBigInt : Num<BigInteger> { public BigInteger Add(BigInteger x, BigInteger y) => x + y; public BigInteger Subtract(BigInteger x, BigInteger y) => x - y; public BigInteger Multiply(BigInteger x, BigInteger y) => x * y; public BigInteger Divide(BigInteger x, BigInteger y) => x / y; public BigInteger FromInteger(int value) => (BigInteger)value; } public static class TestGenericNums { public static void Test() { var a = DoubleIt<NumInt, int>(10); // 20 var b = SquareIt<NumInt, int>(10); // 100 var c = NegateIt<NumInt, int>(10); // -10 var t = DoubleIt<NumDouble, double>(10); // 20 var u = SquareIt<NumDouble, double>(10); // 100 var v = NegateIt<NumDouble, double>(10); // -10 var x = DoubleIt<NumBigInt, BigInteger>(10); // 20 var y = SquareIt<NumBigInt, BigInteger>(10); // 100 var z = NegateIt<NumBigInt, BigInteger>(10); // -10 } public static A DoubleIt<NumA, A>(A value) where NumA : struct, Num<A> => default(NumA).Add(value, value); public static A SquareIt<NumA, A>(A value) where NumA : struct, Num<A> => default(NumA).Multiply(value, value); public static A NegateIt<NumA, A>(A value) where NumA : struct, Num<A> => default(NumA).Subtract(default(NumA).FromInteger(0), value); }