【问题标题】:How can I create temporary objects to pass around without explicitly creating a class?如何在不显式创建类的情况下创建要传递的临时对象?
【发布时间】:2011-10-24 12:51:56
【问题描述】:

我经常发现自己需要创建一个类作为某些数据的容器。它只是简单地使用,但我仍然需要创建类。像这样:

public class TempObject
{
    public string LoggedInUsername { get; set; }
    public CustomObject SomeCustomObject { get; set; }
    public DateTime LastLoggedIn { get; set; }
}


public void DoSomething()
{
    TempObject temp = new TempObject
    {
        LoggedInUsername = "test",
        SomeCustomObject = //blah blah blah,
        LastLoggedIn = DateTime.Now
    };
    DoSomethingElse(temp);
}

public void DoSomethingElse(TempObject temp)
{
    // etc...
}

通常我的临时对象有更多的属性,这就是我想首先将它们分组的原因。我希望有一种更简单的方法,例如使用匿名类型。问题是,当我将它传递给另一个方法时,我不知道要接受什么。类型是匿名的,那我该怎么接受呢?

public void DoSomething()
{
    var temp = new
    {
        LoggedInUsername = "test",
        SomeCustomObject = //blah blah,
        LastLoggedIn = DateTime.Now
    };
    // I have intellisense on the temp object as long as I'm in the scope of this method.
    DoSomethingElse(temp);
}

public void DoSomethingElse(????)
{
    // Can't get my anonymous type here. And even if I could I doubt I would have intellisense.
}

有没有更好的方法来为一堆不同的类型创建一个临时容器,还是每次我需要一个临时对象来将事物组合在一起时都需要定义类?

提前致谢。

【问题讨论】:

  • 开源库 可以检查 thisthis 的帖子。希望对某人有所帮助。
  • 您可以在您的 TempObject 和相关成员上使用 internal 修饰符而不是 public,这样其他程序集将无法使用该类型。

标签: c# .net oop object anonymous-types


【解决方案1】:

Tuple 可能是您正在寻找的解决方案。

public void DoSomething() 
{
    var temp = Tuple.Create("test", "blah blah blah", DateTime.Now);
    DoSomethingElse(temp);
}

public void DoSomethingElse(Tuple<string, string, DateTime> data)
{
    // ...
}

【讨论】:

  • 有趣。是的,这将更符合我正在寻找的内容。
  • KeyValuePair on pre .NET 4.0 虽然它只允许你有两个“成员”。
  • 我会选择这个答案,因为它确实正是我所要求的。但是,我真的不打算使用它,因为在将其付诸实践后,我认为它的可读性不是很高。创建自定义传输对象的名称总是很好,并且对于任何检查代码的人来说都非常易读。有时我可能会发现 Tuple 有用,但是类的轻微开销只会让事情更容易理解和记住。
  • 很好的答案,我想。在 DoSomethingElse 中,我如何访问元组的各个组件?
  • 开源库可以检查thisthis的帖子。希望对某人有所帮助。
【解决方案2】:

The rules 声明

您不能声明字段、属性、事件或返回类型 具有匿名类型的方法。同样,您不能声明 方法、属性、构造函数或索引器的形式参数 具有匿名类型。

就个人而言,我会硬着头皮在这个上,以保持编译时的完整性。

【讨论】:

  • 啊,但是 Jacbo 的元组很可爱!
  • 它是,直到你忘记你的元组参数的顺序。
  • 没错,var newTuple = new Tuple&lt;int,int,string,DateTime,int,bool&gt;(1,2,"hello",DateTime.Now, 3, true); 有点丑。
  • 虽然我的答案使用Tuple 并且有效,但我也推荐这个答案,因为代码更易于阅读且不易出现编码错误。
  • @Jacob,对,但这并不是一个真正的答案,因为我已经在做真实的对象了。
【解决方案3】:

元组是一种干净的方式,但只是为了让您知道即使在其他情况下 C# 也不会让您失望并回答问题,这就是 DoSomethingElse 的样子:

private static void DoSomething(object temp)
        {
            var typedTemp = CastToType(temp, new
                            {
                                LoggedInUsername = "dummy",
                                SomeCustomObject = "dummy",
                                LastLoggedIn = DateTime.Now
                            });

            Console.WriteLine(typedTemp.LastLoggedIn);
        }

private static T CastToType<T>(object obj, T type)
        {
            return (T) obj;
        }

PS:不要-1,我不会用这个,我不要求你用这个:)

【讨论】:

  • 我不会去 -1 或任何东西,但这是迄今为止最糟糕的选择之一。大声笑!
  • @Alex Ford - 就像我说的,只是说有办法!
【解决方案4】:

您可以通过在 C# 4 下声明参数 dynamic 来传递匿名类型。也就是说,我不建议这样做,除非在私有方法中。您会失去类型安全性、IntelliSense 和可读性。

您还可以使用非泛型容器类,例如 ArrayList。但是你又回到了演员阵容,这就是我们首先得到泛型的原因。

我个人会创建课程。查看是否存在涵盖所有类型的抽象并将其声明为接口,然后使用该类型的通用容器。

【讨论】:

  • 我知道 dynamic 关键字,但这完全消除了智能感知并删除了编译时类型检查。如果它是动态的,我可以访问 temp.NonExistentProperty 并且不会收到编译器错误。这绝对是可怕的。
  • @Alex:我同意,这就是为什么我不推荐它用于此用途。但是 tuple.Item1 的含义对读者来说并不明显,因此也有缺点。
  • 我也同意。元组起初看起来很完美,但为了便于阅读,我开始改变主意。
  • @Alex 如果您希望编译器能够检查类型,那么如果您不提供类,您希望它如何做到这一点?
  • @BalamBalam 告诉我,你认为我为什么要发布这个问题?是A)我已经知道答案,还是B)我不知道答案。你有 30 秒的时间……去吧。 ---播放危险主题曲---
【解决方案5】:
    public class GenericObjs
    {
        private List<object> objs = new List<object>();
        public List<object> Objs { get { return objs; } set { objs = value; } }
        public GenericObjs(List<object> Objs) { objs = Objs; }
    }

您可以包含 List String 和 List String 的构造函数...

我只是没有遇到需要扔掉的课程。如果业务对象具有结构,那么类就是定义和实施该结构的方法,而且代码不多。

【讨论】:

  • 这违背了强类型语言的原则,还有更好的方法。 “将所有内容放入对象集合中,huuray”。
  • @MHolzmayr 问题是传递临时对象。
猜你喜欢
  • 2023-03-10
  • 2020-07-25
  • 1970-01-01
  • 2022-11-20
  • 2013-03-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-09
  • 1970-01-01
相关资源
最近更新 更多