将匿名类型设置为null

时间:2011-01-23 14:18:41

标签: c# linq try-catch anonymous-types

我知道不允许将nonymous类型设置为null,但是我该如何解决这个问题:

var products = null; //this cant be null, but somehow it must be declared in this outer scope, and not only inside the try-catch scope

    try
     {
         products = (from p in repository.Products
                     select new { p.Product, p.ProductName }).ToList();
     }
     catch (Exception e)
     {  
       return;
     }
Console.WriteLine(products.FirstOrDefault().ProductName)

7 个答案:

答案 0 :(得分:11)

我同意其他答案,您应该考虑重构此代码或使用名义类型而不是匿名类型。

但是,有一种方法可以在匿名类型的变量中获取空引用。这很容易。

static List<T> GimmeANullListOf<T>(T t) { return (List<T>)null; }
...
var products = GimmeANullListOf(new { X = 1, Y = "hello" });

这个技巧被称为“通过示例施放”,它很奇怪但合法。

答案 1 :(得分:5)

new Nullable<bool>()可以很好地完成工作。

答案 2 :(得分:2)

对于那些简单的事情以及您return例外的事实,您应该能够在try块中执行所有操作,而不必在其外部声明products

try
{
    var products = (from p in repository.Products
                    select new { p.Product, p.ProductName }).ToList();
    Console.WriteLine(products.FirstOrDefault().ProductName);
}
catch (Exception e)
{  
    return;
}

虽然我非常同意SLaks,但你不应该吞下异常并像那样返回。

答案 3 :(得分:2)

没有简单的方法。您的选择要么是更改控制流以将整个事物包装在try{}块中(在这种情况下是微不足道的,但我假设此代码是为了说明目的而简化),或者声明一个具体类型,例如

class ProductWithName
{
    public int Product;
    public string ProductName;
}

然后使用

List<ProductWithName> products = null;

select new ProductWithName { Product = p.Product, ProductName = p.ProductName }

哪种选择最好取决于你的真实代码是什么样的。

答案 4 :(得分:1)

这不是匿名类型,不能为null,它是IEnumerable<T>(或IQueryable),因为你迭代它所以不能为空。

您可以使用products ?? Enumerable.Empty<Product>()将null替换为空IEnumerable<T>

不要吞下这样的例外。在非常具体的场景中捕获Exception基类只是一个好主意,而你的基类不是其中之一。

答案 5 :(得分:1)

你想要的是在声明范围之外使用匿名类型。

你可以用反射来做到这一点:

IEnumerable<object> products = null;

// ...

var anon = products.FirstOrDefault();
Console.WriteLine(anon.GetType().GetProperty("ProductName").GetValue(anon, null));

或动态:

IEnumerable<dynamic> products = null;

// ...

var anon = products.FirstOrDefault();
Console.WriteLine(anon.ProductName);

答案 6 :(得分:0)

由于LINQ延迟执行,您可以在父作用域中定义查询并在try catch块中运行它,如下所示:

var productsDB = new List<Func<string>>() { () => "Apples", () => "Pears", () => "Bannanas" };//, () => { throw new NotImplementedException(); } }; // sorry, couldn't think of a better way to make this fail in 2 mins..

var products = (
    from p in productsDB
    select new 
    {
        Name = p()
    } );

try
{
    products.ToList(); // runs the LINQ query
    products.Dump();   // prints the results (LINQPad)
}
catch { "there was an error".Dump(); }

或者另一个选项是Tuple类,它非常适合这种事情:

var productsDB = new[] { "Apples", "Pears",  "Bannanas" };

List<Tuple<string>> products;

try
{
    products = (
        from p in productsDB
        select Tuple.Create( p ) ).ToList();

    products.Dump();
}
catch { "there was an error".Dump(); }

// Build anonymous type from (read-only) Tuple here if necessary...

编辑:刚刚意识到我误读了帖子:p - 继承我原来的帖子:

我认为只是类型检查员抱怨,尝试这样的事情......

var employees = (
    from person in db.denormalisedPeople
    where person.Type == "employee"
    select new
    {
        name = employee.FullName,
        areaID = new Nullable<int>(), // placeholder.. set in a future query                
    } ).ToList();

(未经测试的代码,但该技术对我来说很好)