15

I have the follow method that returns a dynamic object representing an IEnumerable<'a> ('a=anonymous type) :

    public dynamic GetReportFilesbyStoreProductID(int StoreProductID)
    {
        Report report = this.repository.GetReportByStoreProductID(StoreProductID);

        if (report == null || report.ReportFiles == null)
        {
            return null;
        }

        var query = from x in report.ReportFiles
                    orderby x.DisplayOrder
                    select new { ID = x.RptFileID, Description = x.LinkDescription, File = x.LinkPath, GroupDescription = x.ReportFileGroup.Description };

        return query;
    }

I want to be able to access the Count property of this IEnumerable anonymous type. I'm trying to access the above method using the following code and it is failing:

        dynamic Segments = Top20Controller.GetReportFilesbyStoreProductID(StoreProductID");

        if (Segments.Count == 0)  // <== Fails because object doesn't contain count.
        {
            ...
        }
  • How does dynamic keyword operate?
  • How can I access the Count property of the IEnumerable anonymous type?
  • Is there a way I can use this anonymous type or do I have to create a custom object so that I can pass back a strongly-typed IEnumerable<myObject> instead of dynamic?

I'd prefer to not do that if I can as this method is only called in one place and creating a throw-away object seems like overkill.

Gustavo Mori
  • 8,319
  • 3
  • 38
  • 52
Rodney Hickman
  • 3,133
  • 11
  • 53
  • 83
  • 6
    You should **strongly** consider creating *real* types instead of anonymous types and return an `IEnumerable` of that. Using dynamic for this purpose annihilates all the advantages of static typing. – Kirk Woll Jun 08 '11 at 21:38
  • @Kirk Reports could be dynamic? not exactly in this case but still – Bas Jun 08 '11 at 21:40
  • When you're defining a one-off type just to pass back from a method, there are very few, if any advantages to static typing. – mqp Jun 08 '11 at 21:40
  • @Kirk, This custom object would be a throw-away object that gets used once. Would there be a better option than building out an entire class to use one time? – CatDadCode Jun 08 '11 at 21:40
  • 3
    @Chevex, if the OP is returning this value from a **public** method I fail to see why we think it will only be called once. – Kirk Woll Jun 08 '11 at 21:41
  • @kirk, well I have special insight as he is my co-worker. It will only be called once. – CatDadCode Jun 08 '11 at 21:42
  • 2
    @mquander, I totally disagree that there are no advantages to static typing even in one-off situations. If you are suggesting it would be nice if you could return anonymous types (as that type) from a method, I agree! But you can't. And static typing is *still* endlessly useful in this situation. (intellisense, compile-time safety, etc.) – Kirk Woll Jun 08 '11 at 21:42
  • Have to agree with @Kirk here. If this method were private, returning an anonymous type sequence dynamically is reasonable. However, it's public. – TrueWill Jun 08 '11 at 21:49
  • 1
    @True, not to be argumentative, but I don't think **dynamic** should *ever* be used to chain an anonymous type along. It should never be used because one is too lazy to create a proper type. It should be used for reflection, or dynamic dispatch, or COM, or dynamic scripting. – Kirk Woll Jun 08 '11 at 21:50
  • If you notice, he does not ask how it *should* be used. He asks how to use dynamic in this instance. Whether or not it's the proper choice is irrelevant. He will likely end up statically-typing it anyway, but the answer to the question is still interesting. – CatDadCode Jun 08 '11 at 21:52
  • 2
    @Chevex, yes, and that's why these are comments and not answers. :) – Kirk Woll Jun 08 '11 at 21:56
  • I find it unusual that people are so picky about when `dynamic` is used and isn't used; I get by just fine writing Javascript, Clojure, et al where (gasp) everything is dynamic! However, I agree that it's not idiomatic C# to use `dynamic` in this situation. I would personally make a one-off named type or move things around to eliminate the necessity of doing this. – mqp Jun 08 '11 at 21:58
  • @mquander, by that logic, why not dispense with `var` and named types and use `dynamic` for every type declaration you have? – Kirk Woll Jun 08 '11 at 22:05
  • @Kirk - I've encountered one scenario where it makes sense. You have a LONG Linq-to-Objects statement that uses anonymous types for joins (because of property equality). You want to refactor this, but can't Extract Method because of the anonymous types. You'd not only have to create a class but override Equals and GetHashCode. – TrueWill Jun 08 '11 at 22:28
  • @Kirk: Because the resulting C#-without-types language would suck compared to other modern dynamic languages, and I suspect it would wind up performing poorly in comparison as well. That doesn't really form an argument against isolated uses of `dynamic` to work around awkward bits of C#, though. – mqp Jun 09 '11 at 03:59

5 Answers5

28

You'll need to explicitly call Enumerable.Count().

IEnumerable<string> segments =
  from x in new List<string> { "one", "two" } select x;

Console.WriteLine(segments.Count());  // works

dynamic dSegments = segments;

// Console.WriteLine(dSegments.Count());  // fails

Console.WriteLine(Enumerable.Count(dSegments));  // works

See Extension method and dynamic object in c# for a discussion of why extension methods aren't supported by dynamic typing.

(The "d" prefix is just for the example code - please do not use Hungarian notation!)

Update: Personally I'd go with @Magnus's answer of using if (!Segments.Any()) and return IEnumerable<dynamic>.

Community
  • 1
  • 1
TrueWill
  • 25,132
  • 10
  • 101
  • 150
5

The IEnumerable<T> that's returned from that method doesn't have a Count property, so I don't know what you're talking about. Maybe you forgot to write ToList() on the end to reify it into a list, or you meant to call the Count() method on IEnumerable<T>?

mqp
  • 70,359
  • 14
  • 95
  • 123
  • 1
    There may be no static `Count` property, but there is the `Count()` LINQ extension. I think his point is that he doesn't know how to use the dynamic object that comes back. – CatDadCode Jun 08 '11 at 21:42
  • Well, he'd be using it correctly, if he happened to be referring to a property or method that actually exists, so he must have just mixed something up. – mqp Jun 08 '11 at 21:42
  • Ah true, I will inform him to add parenthesis to the Count call. – CatDadCode Jun 08 '11 at 21:45
2

Count() needs to enumerate to complete collection, you probably want:

if (!Segments.Any()) 
{
}

And your function should return IEnumerable<object> instead of dynamic

Magnus
  • 45,362
  • 8
  • 80
  • 118
  • +1 - I had to try it, but this works. Although I suspect the OP will want to return IEnumerable in order to get at the properties of the anonymous type. – TrueWill Jun 09 '11 at 02:17
0

You could use the property Length too!

if (!Segments.Length)
{
    `enter code here`
}
alvescleiton
  • 1,063
  • 11
  • 8
0

Try the Linq countusing System.Linq; Segments.Count()

Bas
  • 26,772
  • 8
  • 53
  • 86