代码之家  ›  专栏  ›  技术社区  ›  cllpse

选择新对象作为参数,同时保留其运行时生成的类型

  •  3
  • cllpse  · 技术社区  · 14 年前

    考虑以下几点:

    // select a subset of the DataTable
    var subset = DataTable.Where(...).Select(row => new
    {
        Id = Convert.ToInt32(row["Id"]),
        Name = row["Name"].ToString(),
        Email = row["Email"].ToString()
    });
    
    // or create a new object
    var subset = new {
        Id = 1,
        Name = "something random",
        Email = "name@domain.tld"
    };
    

    有没有办法使用 Object ? 你能携带自动生成的变量类型吗?

    每次我想把LINQ子集传递给方法时,我都尽量避免创建新的类。

    随机通用方法是受欢迎的。

    5 回复  |  直到 14 年前
        1
  •  2
  •   Mark Byers    14 年前

    var subset = DataTable.Where(...).Select(row => new SomeType
    {
        Id = Convert.ToInt32(row["Id"]),
        Name = row["Name"].ToString(),
        Email = row["Email"].ToString()
    });
    

    或者您可以使用 Tuple 一些


    *实际上 there is a workaround ,但我认为这是一个丑陋的黑客,并建议你不要这样做。

        2
  •  2
  •   Marc Gravell    14 年前

    输入以通过API公开,而您不必做任何工作。这也为您提供了创建不可变(如匿名类型)或可变、嵌套和顶层等选项。

    顺便说一句,我不推荐 struct 这里(从问题开始)。

    进入之内 Action<int,string,string> callback -然后像这样做:

    foreach(item in query) callback(item);
    

    但是,我不喜欢这样,因为不明显的是:

    DoSomething(args, (id, email, name) => Email(To: email, Subject: name));
    

    (错误在于 (id, name, email) ,如果你明白我的意思)

        3
  •  1
  •   Jon Skeet    14 年前

    可以使用泛型方法:

    public static void Foo<T>(T item)
    {
        // Do whatever
    }
    

    如果你打电话来

    Foo(subset);
    

    编译器将推断 T 为你。不管那是不是真的 你是另一回事。。。这取决于这个方法要做什么。很明显 Foo 无法引用 Id Name Email 等。

    通常,如果多个方法应该知道相同的成员,那么应该使用命名类型。将它们传递给泛型方法的通常情况是,该方法实际上并不关心所涉及的类型,例如在LINQ中。

    我已经为C#5提出了一个特性请求,我们应该能够创建与匿名类型具有所有相同特性的类型(不变性、相等性、哈希代码生成、, ToString

        4
  •  0
  •   bruno conde    14 年前

    如果您需要将匿名类型传递给一个方法,那么这个方法要么是非常通用的,比如(示例)

    void PrintAllObjectProperties(object obj);
    

        5
  •  0
  •   cllpse    14 年前

    这是我想到的。。。


    对象的扩展方法:

    public static class ObjectExtensions
    {
        /// <summary>
        /// Cast Object to anonymous type.
        /// E.G.: new Object().ToAnonymousType(new { Property = new Type() });
        /// </summary>
        public static T ToAnonymousType<T>(this Object o, T t)
        {
            return (T)o;
        }
    }
    

    用法:

    public void HandleAnonymousTypeAsParameter(Object o)
    {
        var anonymousType = o.ToAnonymousType(new
        {
            Id = new Int32(),
            Foo = new String(),
            Bar = new String()
        });
    
    
        // ... You can do this in even less characters:
        var anonymousType = o.ToAnonymousType(new { Id = 0, Foo = "", Bar = "" });
    }
    
    
    HandleAnonymousTypeAsParameter(new
    {
        Id = 1,
        Foo = "foo",
        Bar = "bar"
    });