kiss my armpit
kiss my armpit

Reputation: 3519

How to initialize generic local variable?

The objective is to create a simple program that calculates the sum of pre-processed set. The Sum must be generic to allow it accepts both integer and floating point set.

The following code does not compile. Could you tell me how to fix it?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{

    static class Program
    {
        delegate T del<T>(T x);
        static T Sum<T>(del<T> df, IEnumerable<T> data)
        {
            T s = 0;
            foreach (var x in data) s += df(x);
            return s;
        }

        static void Main(string[] args)
        {
            var data = Enumerable.Range(1, 4);
            int sum = Sum<int>(x => x * x, data);
            Console.WriteLine(sum);
        }
    }
}

Error Messages (roughly speaking):

  1. cannot convert int to T.
  2. += is not available for T.

Upvotes: 1

Views: 1106

Answers (4)

Timothy Walters
Timothy Walters

Reputation: 16884

You need to use the default keyword, specifically:

// was: T s = 0;
T s = default(T);

I replied in haste to the question in the title, on the secondary issue of performing add operations between generics, this has been covered in another StackOverflow question, so I wont double post. It involves using dynamic, which means you no longer have compile-time safety. Read the other question for more details.

Upvotes: 0

Fredou
Fredou

Reputation: 20140

VERY similar to Simon Whitehead answer

    static T Sum<T>(del<T> df, dynamic data)
    {
        T s = default(T);
        foreach (var x in data) s += df(x);
        return s;
    }

this return also 30

Upvotes: 0

zs2020
zs2020

Reputation: 54541

You can use the generic Add() method defined here.

The trick is to pass the initial value of s as the type T into the Sum() method instead of initializing it inside the function.

public class Program
{
    public static T Add<T>(T a, T b)
    {
        var paramA = Expression.Parameter(typeof (T), "a");
        var paramB = Expression.Parameter(typeof (T), "b");
        var body = Expression.Add(paramA, paramB);
        var add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();
        return add(a, b);
    }

    public delegate T del<T>(T x);

    //pass the variable s into the function instead of initializing it inside the function.
    public static T Sum<T>(T s, del<T> df, IEnumerable<T> data)
    {
        return data.Aggregate(s, (current, x) => Add(current, df(x)));
    }

    public static void Main(string[] args)
    {
        var data = Enumerable.Range(1, 4);
        int sum = Sum(0, x => x * x, data);
        Console.WriteLine(sum);
    }
}

Upvotes: 1

Simon Whitehead
Simon Whitehead

Reputation: 65107

Ignoring the other issues with your code, you can't do what you're trying to do. C# does not support arithmetic operators on generic types.

Therefore, one option will be to Sum(del<int>, ..), Sum(del<float>, ...).. etc.

Or, use dynamic:

delegate T del<T>(T x);
static T Sum<T>(del<T> df, IEnumerable<T> data) 
{
    dynamic s = default(T);
    foreach (var x in data) s += df(x);
    return s;
}

This results is 30 for your provided example.

Upvotes: 3

Related Questions