什么是在函数中声明数据结构的替代方法?

时间:2012-09-19 11:07:25

标签: c# data-structures scope

C#中是否有一个好的现有或即将出现的替代方法来声明方法中的数据结构?可以使用匿名类型,但是声明它们有困难。假设我有一个假设的课程:

class ThingsManager
{
    private void DoThings(IEnumerable<Thing> things)
    {
        var thingLocations = new Dictionary<string, string>();

        foreach(var thing in things)
        {
            // some complicated logic and checks for current thing;
            // if current thing satisfies all conditions:

            var thingName = thing.Name;
            var thingLocation = location; // taken somewhere from upper lines
            thingLocations.Add(thingName, thingLocation);
        }

        // ... later

        foreach(var thingLocation in thingLocations)
        {
            // here I don't know what is the key and what does the value mean.
            // I could use Linq and anonymous types, but sometimes it is clearer 
            // to use foreach if the logic is complicated
        }
    }
}

现在,我想看到:

class ThingsManager
{
    private void DoThings(IEnumerable<Thing> things)
    {
        struct ThingLocations
        {
            string ThingName {get;set;}
            string Location {get;set;}
        }

        var thingLocations = new List<ThingLocations>();

        foreach(var thing in things)
        {
            // some complicated logic and checks for current thing;
            // if current thing satisfies all conditions:

            var thingName = thing.Name;
            var thingLocation = location; // taken somewhere from upper lines
            thingLocations.Add(new ThingLocation(thingName, thingLocation));
        }

        // ... later

        foreach(var thingLocation in thingLocations)
        {
            // now here I can use thingLocation.ThingName  
            // or thingLocation.Location
        }
    }
}

我也可以在类中声明结构,但除了在我的函数中使用它没有任何意义。如果我的函数是唯一可以使用此数据结构的地方,那会更好。我正在寻找一种更好的方法来处理这种情况,或者至少能够声明匿名类型。

2 个答案:

答案 0 :(得分:0)

C#确实支持Anonymous Types,但真正的答案是:

不,你不能在C#中做到这一点。只需将struct声明为私有,然后忘记它。

答案 1 :(得分:0)

匿名类型有助于命名方面,但您必须将输入转换为匿名类型,并且类型将保留在方法范围内部。

// Assumes thingLocation comes from somewhere...
var thingLocations = things
    .Select(t => new { ThingName = t.Name, Location = new ThingLocation(t.Name, thingLocation) } );

使用Select扩展方法完成,以便投射到匿名类型。

你可以在没有linq的情况下声明匿名类型,但是你会发现尝试将它们添加到列表/词典时很烦人:

var me = new { Name = "Adam", Age = 27 };

<小时/> 我正在记录中说我不会采用这种方法,我个人会使用匿名类型,Tuple<string, string>或自定义类型。

没有完成所有这些,如果你不介意启动DLR,你可以使用ExpandoObject

    class Thing
    {
        public string Name;
    }

    static void Main(string[] args)
    {
        var things = new List<Thing>() { new Thing { Name = "Adam" } };
        var thingLocations = new List<dynamic>();

        foreach (var thing in things)
        {
            dynamic location = new ExpandoObject();
            location.Name = thing.Name;
            location.Location = "here";

            thingLocations.Add(location);
        }

        // ... later

        foreach(var thingLocation in thingLocations)
        {
            Console.WriteLine(thingLocation.Name);
            Console.WriteLine(thingLocation.Location);
        }

        Console.ReadLine();
    }

这允许您通过在现场声明属性来动态添加属性。然后,您可以稍后使用它们,因为{DL}在DLR按名称要求成员时为DLR提供管道。