简体   繁体   中英

C# Complex Return Types

I am new to C# and find myself in situations sometimes where I have to return complex return types for some functions. Like the function may take in some object and return a different view of that object: some fields added, some removed, etc. And other times, I may take in a list of objects and want to return a list of some modified objects and possibly some aggregate calculations on all of them together.

I could accomplish these kinds of things by returning C# native types (like object[]), but it gets ugly to have object[] of object[]'s and then in code have to "know" that object[0][1] corresponds to something.

I suspect it makes sense to create a truly new class called like a FnFooReturn, but then where does it make the most sense to include the definition of such classes so that anywhere that calls the function can use it?

Edit: A specific example: I have a function Foo that takes in a list of objects like:

(int id, int num, string name)

so some example data could be:

(1, 100, "foo")
(1, 203, "foo")
(2, 400, "bar")
(3, 10, "cat")

and I want to return a list of objects like:

(int id, string name, int[] nums)

to look like:

[(1, "foo", [100, 103]), (2, "bar", [400]), (3, "cat", [10])]

so basically it is just a different view of the original list of objects except it combines together all of the objects with the same id to make it easier to loop over in other code later.

You can add an ordinary class to your project and use it wherever you like.

Try LINQ :

var items = new[] {
    new { id = 1, num = 100, name = "foo" },
    new { id = 1, num = 203, name = "foo" },
    new { id = 2, num = 400, name = "bar" },
    new { id = 3, num = 10, name = "cat" },
};

var result = items.GroupBy(x => x.id, (k, i) => new { id = k, nums = i.Select(y => y.num).ToArray(), name = i.Select(x => x.name).First() }).ToArray();

If you need encapsulate this logic into a method, use an Extension Method on your list (and empower it with Generics if needed).

Your functions should be like b = F(a) where a and b are menaingful types in your design.

There is some limited room for ad-hoc types, like Tuple<Customer, decimal> but if you find yourself writing special classes to accomodate a method, something has gone wrong.

In your specific example you should have a concrete type which handles those properties, and utilize LINQ to reinterpret the data in a different "view" .

public class Item
{
    public int Id { get; private set; }
    public int Category { get; set; }
    public string Name { get; set; }

    public Item(int id, int category, string name)
    {
        this.Id = id;
        this.Category = category;
        this.Name = name;
    }
}

Later:

var items = new [] { new Item(1, 103, "foo"), ... };

var query = from item in items
            where item.Category != 108 /* example */
            group by item.Id into g
            select new
            {
                Id = g.Key,
                Categories = g.Select(x => x.Category).ToArray()
            };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM