Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 945593
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T22:46:36+00:00 2026-05-15T22:46:36+00:00

Imagine the following simple code: public void F<T>(IList<T> values) where T : struct {

  • 0

Imagine the following simple code:

public void F<T>(IList<T> values) where T : struct
{
  foreach (T value in values)
  {
    double result;
    if (TryConvertToDouble((object)value, out result))
    {
      ConsumeValue(result);
    }
  }
}

public void ConsumeValue(double value)
{
}

The problem with the above code is casting to object, which results in boxing in the loop.

Is there a way to achieve the same functionality, i.e. feeding ConsumeValue with all the values without resorting to boxing in the foreach loop? Note, that F must be a generic method.

I can live with an expensive preparation code as long as it is executed outside the loop just once. For instance, if a fancy dynamic method needs to be emitted, then it is fine if done just once.

Edit

T is guaranteed to be of some numeric type or bool.

Motivation. Imagine meta data driven application, where an agent reports a data stream, where data item type is dynamically emitted based on the data stream meta data. Imagine also, that there is normalizer engine, which knows to normalize numeric data streams according to some algorithm. The type of the incoming numeric data stream is known only at run time and can be directed to a generic method of that data type. The normalizer, however, expects doubles and produces doubles. This is just a very high level description.

Edit 2

Concerning the cast to double. Actually we have a method to convert to double with the following signature:

bool TryConvertToDouble(object value, out double result);

I should have used it in the example in the first place, but I wanted to save space and written something that is not going to work. Fixed it now.

Edit 3

The current implementation does box the values. And even if I do not have the profiler’s verdict as to performance penalty of it (if any), still I am interesting to know whether there is a solution without boxing (and without converting to string). Let me call it purely academic interest.

This really interests me, because things like that are trivial in C++ with templates, but, of course, I am not starting an argument over whether .NET generics or C++ templates are better.

Edit 4

Thanks to https://stackoverflow.com/users/267/lasse-v-karlsen who provided the answer. Actually, I have used his code sample to write a simple class like this:

public static class Utils<T>
{
  private static class ToDoubleConverterHolder
  {
    internal static Func<T, double> Value = EmitConverter();

    private static Func<T, double> EmitConverter()
    {
      ThrowIfNotConvertableToDouble(typeof(T));

      var method = new DynamicMethod(string.Empty, typeof(double), TypeArray<T>.Value);
      var il = method.GetILGenerator();

      il.Emit(OpCodes.Ldarg_0);
      if (typeof(T) != typeof(double))
      {
        il.Emit(OpCodes.Conv_R8);
      }
      il.Emit(OpCodes.Ret);

      return (Func<T, double>)method.CreateDelegate(typeof(Func<T, double>));
    }
  }

  public static double ConvertToDouble(T value)
  {
    return ToDoubleConverterHolder.Value(value);
  }
}

Where:

  • ThrowIfNotConvertableToDouble(Type) is a simple method that makes sure the given type can be converted to double, i.e. some numeric type or bool.
  • TypeArray<T> is a helper class to produce new[]{ typeof(T) }

The Utils<T>.ConvertToDouble method converts any numeric value to double in the most efficient way, shown by the answer to this question.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T22:46:37+00:00Added an answer on May 15, 2026 at 10:46 pm

    NOTE: There was a bug in my initial code for instance-based code generation. Please re-check the code below. The changed part is the order of loading values onto the stack (ie. the .Emit lines). Both the code in the answer and the repository has been fixed.

    If you want to go the route of code generation, as you hint to in your question, here’s sample code:

    It executes ConsumeValue (which does nothing in my example) 10 million times, on an array of ints and an array of booleans, timing the execution (it runs all the code once, to remove JIT overhead from skewing the timing.)

    The output:

    F1 ints = 445ms         <-- uses Convert.ToDouble
    F1 bools = 351ms
    F2 ints = 159ms         <-- generates code on each call
    F2 bools = 167ms
    F3 ints = 158ms         <-- caches generated code between calls
    F3 bools = 163ms
    

    Roughly 65% less overhead with code generation.

    The code:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace ConsoleApplication15
    {
        class Program
        {
            public static void F1<T>(IList<T> values) where T : struct
            {
                foreach (T value in values)
                    ConsumeValue(Convert.ToDouble(value));
            }
    
            public static Action<T> GenerateAction<T>()
            {
                DynamicMethod method = new DynamicMethod(
                    "action", MethodAttributes.Public | MethodAttributes.Static,
                    CallingConventions.Standard,
                    typeof(void), new Type[] { typeof(T) }, typeof(Program).Module,
                    false);
                ILGenerator il = method.GetILGenerator();
    
                il.Emit(OpCodes.Ldarg_0); // get value passed to action
                il.Emit(OpCodes.Conv_R8);
                il.Emit(OpCodes.Call, typeof(Program).GetMethod("ConsumeValue"));
                il.Emit(OpCodes.Ret);
    
                return (Action<T>)method.CreateDelegate(typeof(Action<T>));
            }
    
            public static void F2<T>(IList<T> values) where T : struct
            {
                Action<T> action = GenerateAction<T>();
                foreach (T value in values)
                    action(value);
            }
    
            private static Dictionary<Type, object> _Actions =
                new Dictionary<Type, object>();
            public static void F3<T>(IList<T> values) where T : struct
            {
                Object actionObject;
                if (!_Actions.TryGetValue(typeof(T), out actionObject))
                {
                    actionObject = GenerateAction<T>();
                    _Actions[typeof (T)] = actionObject;
                }
                Action<T> action = (Action<T>)actionObject;
                foreach (T value in values)
                    action(value);
            }
    
            public static void ConsumeValue(double value)
            {
            }
    
            static void Main(string[] args)
            {
                Stopwatch sw = new Stopwatch();
    
                int[] ints = Enumerable.Range(1, 10000000).ToArray();
                bool[] bools = ints.Select(i => i % 2 == 0).ToArray();
    
                for (int pass = 1; pass <= 2; pass++)
                {
                    sw.Reset();
                    sw.Start();
                    F1(ints);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F1 ints = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    F1(bools);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F1 bools = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    F2(ints);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F2 ints = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    F2(bools);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F2 bools = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    F3(ints);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F3 ints = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    F3(bools);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F3 bools = "
                            + sw.ElapsedMilliseconds + "ms");
                }
            }
        }
    }
    

    Note that if you make GenerationAction, F2/3 and ConsumeValue non-static, you have to change the code slightly:

    1. All Action<T> declarations becomes Action<Program, T>

    2. Change the creation of the DynamicMethod to include the "this" parameter:

       DynamicMethod method = new DynamicMethod(
           "action", MethodAttributes.Public | MethodAttributes.Static,
           CallingConventions.Standard,
           typeof(void), new Type[] { typeof(Program), typeof(T) },
           typeof(Program).Module,
           false);
      
    3. Change the instructions to load the right values at the right times:

       il.Emit(OpCodes.Ldarg_0); // get "this"
       il.Emit(OpCodes.Ldarg_1); // get value passed to action
       il.Emit(OpCodes.Conv_R8);
       il.Emit(OpCodes.Call, typeof(Program).GetMethod("ConsumeValue"));
       il.Emit(OpCodes.Ret);
      
    4. Pass "this" to the action whenever it is called:

       action(this, value);
      

    Here’s the complete changed program for non-static methods:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace ConsoleApplication15
    {
        class Program
        {
            public void F1<T>(IList<T> values) where T : struct
            {
                foreach (T value in values)
                    ConsumeValue(Convert.ToDouble(value));
            }
    
            public Action<Program, T> GenerateAction<T>()
            {
                DynamicMethod method = new DynamicMethod(
                    "action", MethodAttributes.Public | MethodAttributes.Static,
                    CallingConventions.Standard,
                    typeof(void), new Type[] { typeof(Program), typeof(T) },
                    typeof(Program).Module,
                    false);
                ILGenerator il = method.GetILGenerator();
    
                il.Emit(OpCodes.Ldarg_0); // get "this"
                il.Emit(OpCodes.Ldarg_1); // get value passed to action
                il.Emit(OpCodes.Conv_R8);
                il.Emit(OpCodes.Call, typeof(Program).GetMethod("ConsumeValue"));
                il.Emit(OpCodes.Ret);
    
                return (Action<Program, T>)method.CreateDelegate(
                    typeof(Action<Program, T>));
            }
    
            public void F2<T>(IList<T> values) where T : struct
            {
                Action<Program, T> action = GenerateAction<T>();
                foreach (T value in values)
                    action(this, value);
            }
    
            private static Dictionary<Type, object> _Actions =
                new Dictionary<Type, object>();
            public void F3<T>(IList<T> values) where T : struct
            {
                Object actionObject;
                if (!_Actions.TryGetValue(typeof(T), out actionObject))
                {
                    actionObject = GenerateAction<T>();
                    _Actions[typeof (T)] = actionObject;
                }
                Action<Program, T> action = (Action<Program, T>)actionObject;
                foreach (T value in values)
                    action(this, value);
            }
    
            public void ConsumeValue(double value)
            {
            }
    
            static void Main(string[] args)
            {
                Stopwatch sw = new Stopwatch();
    
                Program p = new Program();
                int[] ints = Enumerable.Range(1, 10000000).ToArray();
                bool[] bools = ints.Select(i => i % 2 == 0).ToArray();
    
                for (int pass = 1; pass <= 2; pass++)
                {
                    sw.Reset();
                    sw.Start();
                    p.F1(ints);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F1 ints = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    p.F1(bools);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F1 bools = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    p.F2(ints);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F2 ints = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    p.F2(bools);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F2 bools = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    p.F3(ints);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F3 ints = "
                            + sw.ElapsedMilliseconds + "ms");
    
                    sw.Reset();
                    sw.Start();
                    p.F3(bools);
                    sw.Stop();
                    if (pass == 2)
                        Console.Out.WriteLine("F3 bools = "
                            + sw.ElapsedMilliseconds + "ms");
                }
            }
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Imagine the following situation: struct Args { bool arg; }; void thing(Args arg) {
Consider the following sample code: class MyClass { public long x; public void DoWork()
Imagine the following two entities. Element is simple class containing some data: @Entity public
Imagine the following folder structure: project src code.c makefile bin How can I compile
imagine the following simple Models (example for simplicity reasons; in fact, we have MVVM
Let's imagine we got the following: A) Factory interface such as public interface IEmployeeFactory
yeah :( simple question * blush * Lets imagine i have the following enumeration:-
Imagine following scenario: We have a lot of parallel development going on in several
Imagine the following scenario: class MyClass extends OtherClass<String>{ String myName; //Whatever } class OtherClass<T>
Imagine the following table (called TestTable ): id somedate somevalue -- -------- --------- 45

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.