Click here to Skip to main content
14,690,505 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Thank you for your help! I have a simple list of fruits, inside a list. I created a generic local function that received a list<t>... the problem comes when I want to iterate this list, the program does not understand what the object of <t> is... in this case a fruit, so I can't access any member... please check my code and if possible, provide me with a solution..., thank you!!

What I have tried:

<pre>public class Fruit
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class ImporterController : Controller    {        
        public IActionResult Racks()
        {

            List<Fruit> Fruits = new List<Fruit> { 
                 new Fruit{Id = 1, Name = "Mango"}
                 , new Fruit{Id =2, Name="Banana" }
            };

            ProcessMyList<Fruit>(Fruits);

            void ProcessMyList<T>( List<T> list)
            {

                foreach (T thing in list)
                {
                    Debug.WriteLine(thing.Name); /* LINE CAUSING THE PROBLEM */
                }

            }

            return Json("done");
        }
    }
Posted
Updated 15-Sep-20 0:05am

Another option would be to use a generic type constraint with an interface:
public interface IHaveName
{
    string Name { get; }
}

public class Fruit : IHaveName
{
    public int Id { get; set; }
    public string Name { get; set; }
}
void ProcessMyList<T>(IEnumerable<T> list) where T : IHaveName
{
    foreach (T thing in list)
    {
        Debug.WriteLine(thing.Name);
    }
}
You also don't need to specify the generic type parameter when you call the function. The compiler can infer that for you:
List<Fruit> fruits = ...;
ProcessMyList(fruits);
   
Comments
Maciej Los 15-Sep-20 6:04am
   
I like it!
If you want to access the properties of the item in the List then you can no longer treat it as being generic.

void ProcessMyList(List<Fruit> list)
{
    foreach (Fruit thing in list)
    {
        Debug.WriteLine(thing.Name);
    }
}


If you are planning on having other classes that inherit from fruit then you can keep the function generic so it will work on your derived classes to and add a stipulation that the class is based on Fruit.

void ProcessMyList<T>(List<T> list) where T : Fruit
{

    foreach (T thing in list)
    {
        Debug.WriteLine(thing.Name);
    }
}
   
Inside your generic method, T is defined at runtime and thus you cannot write a code that access the property at compile time - thus the error.

BTW, If you access a hardcoded property in your Generic method, it kind of defeats the purpose of using Generic. Assume you want to use the same generic method ProcessMyList for another class Address and it does not have 'Name' property in it. What would happen then?

For learning purpose to resolve above, if you want to access properties from the Type passed (Fruit) here, you need to first get the type. Once you know the type, you can access property accordingly.

Option 1: Reflection
foreach (T thing in list)
{
    var value = typeof(T).GetProperty("Name").GetValue(thing);
    Console.WriteLine(obj.Name); 
}

Option 2: dynamic keyword
foreach (T thing in list)
{
    dynamic currobj = thing; 
    Console.WriteLine(currobj.Name); 
}

In order to keep the method still generic,
- you can add an additional parameter of 'property name' to get and then use that during reflection.
- you can come up with a class design such that all classes that inherits from a defined interface or abstract class can use the above generic method.
   
Comments
BillWoodruff 13-Sep-20 3:33am
   
+5 Really useful explanation
Sandeep Mewara 13-Sep-20 8:02am
   
:thumbsup:
Guillermo Perez 13-Sep-20 14:41pm
   
I did remember also the "unboxing" section of my book... (pro c#) and they did it like this:

foreach (T thing in list){
var Thing = thing as Fruit
if (Thing != null)...
}
Maciej Los 15-Sep-20 6:03am
   
A 5 from me too!
Sandeep Mewara 15-Sep-20 6:20am
   
Thanks Maciej!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900