0

I have a List which I would like to populate with different types of objects, trying to do it with object\dynamic, but it doesn't, even when casting. using asp.net core. See my code:

public Dictionary<string, Employee> getEmployees(); //This method returns a dictionary of string as a key and Employee as a value.
public Dictionary<string, customer>()> getCustomers(); //same principal


public List<Dictionary<string, object>> getDifferentItems()
{
   List<Dictionary<string, object>> listOfItems = new List<Dictionary<string, object>>();
   listOfItems.add(getEmployees()); //Error
   listOfItems.add(getCustomers()); //Error
   return listOfItems;
}
6
  • Is new List<string, object> a typo? Commented Feb 27, 2020 at 13:23
  • 1
    List<T> only takes one type parameter - what exactly do you mean by List<string, object> here? did you mean that to be Dictionary<string, object>? or...? Note: you can't cast a Dictionary<string, Employee> to Dictionary<string, object> - that's not how "variance" works Commented Feb 27, 2020 at 13:25
  • Type errors- sorry, it is a pseudo code I wrote. Fixing it soon Commented Feb 27, 2020 at 13:34
  • @Johnathan Barclay- I Fixed the code Commented Feb 27, 2020 at 13:36
  • @Marc Gravell - I Fixed the code Commented Feb 27, 2020 at 13:36

4 Answers 4

1

Depending on what you are trying to do, I can see two solutions:

Create a list of TWO different dictionaries

    public Dictionary<string, Employee> getEmployees() {
        return new Dictionary<string, Employee>();
    }
    public Dictionary<string, Customer> getCustomers() {
        return new Dictionary<string, Customer>();
    }


    public List<Dictionary<string, object>> getDifferentItems()
    {
        List<Dictionary<string, object>> listOfItems = new List<Dictionary<string, object>>();
        listOfItems.Add(this.getEmployees().ToDictionary(entry => (string)entry.Key,
                  entry => (object)entry.Value)); 
        listOfItems.Add(this.getCustomers().ToDictionary(entry => (string)entry.Key,
                  entry => (object)entry.Value)); 
        return listOfItems;
    }

Create one dictionary with all the values

    public Dictionary<string, Employee> getEmployees() {
        return new Dictionary<string, Employee>();
    }
    public Dictionary<string, Customer> getCustomers() {
        return new Dictionary<string, Customer>();
    }


    public Dictionary<string, object> getDifferentItems()
    {
        Dictionary<string, object> listOfItems = new Dictionary<string, object>();
        foreach (var entry in getEmployees()) {
            listOfItems.Add(entry.Key, entry.Value);
        }
        foreach (var entry in getCustomers()) {
            listOfItems.Add(entry.Key, entry.Value);
        }
        return listOfItems;
    }
Sign up to request clarification or add additional context in comments.

Comments

0

There are a couple of issues here, both related to variance.

This won't work because List<T>, or any other class in .NET for that matter, does not support variance.

In other words T has to be a specific type, and does not respect inheritance / substitutability as with non-generic types.

Similarly, for Dictionary<TKey, TValue>, TValue is not variant, so you can't simply use object as the value.

IEnumerable<out T> on the other hand is covariant so you could do this:

public IEnumerable<IDictionary> getDifferentItems()
{
   yield return getEmployees();
   yield return getCustomers();
}

IDictionary is used, as it is the only common ancestor (other than object) to Dictionary<string, Employee> and Dictionary<string, Customer>.

This may satisfy your requirements, but you don't make clear whay you are trying to achive with your getDifferentItems method.

More information on variance can be found here.

1 Comment

thanks - It is basically used in a rest method - to get collection of static lookup tables. In my code the container (List) is replaced by a dictionary<string, dictionary<string, object>> to get identifier for the table name as a key, and its content (key, value) as a value
0

I'd personally make an interface, such as IPerson that has all the properties of Employees and Customers, such as Name, Address, ID, etc.

Set up your Customer and employee classes to implement IPerson

Then use a IPerson in your dictionary and you can add to the objects to that.

Here's some code:

public class Employee : IPerson
    {
        public int ID { get; set; }

        public string Name { get; set; }
    }

    public class Customer : IPerson
    {
        public int ID { get; set; }

        public string Name { get; set; }
    }

    public interface IPerson
    {
        int ID { get; set; }

        string Name { get; set; }
    }
    public class Test
    {
        public void MyTest()
        {
            List<Dictionary<string, IPerson>> listOfItems = new List<Dictionary<string, IPerson>>();

            Dictionary<string, IPerson> myEmployees = new Dictionary<string, IPerson>();
            string someString = "blah";
            Employee e = new Employee();
            e.Name = "Bob";
            e.ID = 1;

            myEmployees.Add(someString, e);

            Dictionary<string, IPerson> myCustomers = new Dictionary<string, IPerson>();
            string someOtherString = "blah";
            Customer c = new Customer();
            c.Name = "Robert";
            c.ID = 2;

            myCustomers.Add(someOtherString, c);

            listOfItems.Add(myEmployees);
            listOfItems.Add(myCustomers);
        }
    }

5 Comments

this was my initial thought, but the types are already there, very different, with no similar properties
If the two types don't have similiar properties I think you should give more thought to the purpose of doing what your doing. If Customers and Employees aren't similiar why are you returning a list of them intermingled to the caller? Since you said it's a rest method, maybe there should be a separate calls for employees and customers or maybe there should be one overall object that contains two collections, 1 for employees and 1 for customers. Also, IPerson could have a union of the various properties and you only implement based on if it's Customer or Employee.
these 2 objects are just examples. The tables I refer to were already mapped to dictionary types where their value can be, for example, an atomic string or an object. Additionally - I would like to make a one call for all the lookups.
Have you thought about making a dictionary of string and datatable since you're essentially just trying to return all the static lookup tables?
No, not thought of it, I passing the data as json, I'm not sure that it has benefits
0

Here is another solution :

    public class Test
    {
        Dictionary<string, object> listOfItems = new Dictionary<string, object>();
        List<Employee> employees = new List<Employee>();
        List<customer> customers = new List<customer>();
        public Dictionary<string, object> getEmployees()
        {
            return employees.GroupBy(x => x.name, y => (object)y).ToDictionary(x => x.Key, y => y.FirstOrDefault());

        }//This method returns a dictionary of string as a key and Employee as a value.
        public Dictionary<string, object> getCustomers()
        {
            return customers.GroupBy(x => x.name, y => (object)y).ToDictionary(x => x.Key, y => y.FirstOrDefault());
        } //same principal 
        public Dictionary<string, object> getDifferentItems()
        {
            listOfItems = getEmployees();
            listOfItems.Concat(getCustomers());
            return listOfItems;
        }
    }
    public class Employee
    {
        public string name { get;set;}
    }
    public class customer
    {
        public string name { get;set;}
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.