Casey Crookston
Casey Crookston

Reputation: 13965

Avoid an inner .ToList() in a LINQ query?

I am building a method that takes a List<T> and turns it into a DataTabe. In the process, I want to filter out any properties that are tagged with the [NotMapped] attribute.

I have the entire method working, but I am a bit worried about one part of it... the part that weeds out the [NotMapped] properties. Here's what I've got:

    public static DataTable CreateDataTable<T>(IEnumerable<T> list)
    {
        Type type = typeof(T);

        var properties = type.GetProperties().Where(p =>
                        p.CustomAttributes.ToList().Count == 0 ||
                        (p.CustomAttributes.ToList().Count > 0 && p.CustomAttributes.ToList()[0].AttributeType.Name != "NotMappedAttribute")
                        ).ToList();

        // Rest of the method...
    }

So, that works as I'd like it to and gets rid of anything that looks like this (for example) so it doesn't end up in the final DataTable:

    [NotMapped]
    public string Description { get; set; }

My concern is about performance and just general best practice. The var properties = LINQ query seems clumsy to me, but I'm not seeing a more efficient way to improve it.

Namely, I don't like calling p.CustomAttributes.ToList() 3 times. Is there a way to avoid this?

Upvotes: 0

Views: 125

Answers (2)

user47589
user47589

Reputation:

To answer the original question, you can avoid calling ToList() multiple times by saving its return value:

type.GetProperties().Where(p =>
                    p.CustomAttributes.ToList().Count == 0 ||
                    (p.CustomAttributes.ToList().Count > 0 && p.CustomAttributes.ToList()[0].AttributeType.Name != "NotMappedAttribute")
                    )

... becomes...

type.GetProperties().Where(p => 
{
    var attrs = p.CustomAttributes.List();
    return attrs.Count == 0 || (attrs.Count > 0 && attrs[0].AttributeType.Name != "NotMappedAttribute");
})

However, I recommend instead doing this:

type.GetProperties().Where(p => p.GetCustomAttribute<NotMappedAttribute>() == null))

Its shorter and easier to understand at a glance.

Upvotes: 0

Scott Hannen
Scott Hannen

Reputation: 29312

private IEnumerable<PropertyInfo> GetPropertiesWithoutAttribute<TAttribute>(Type type) 
    where TAttribute : Attribute
{
    return type.GetProperties().Where(p => !p.GetCustomAttributes<TAttribute>().Any());
}

Upvotes: 3

Related Questions