C# 将匿名类型设置为null

C# 将匿名类型设置为null,c#,linq,try-catch,anonymous-types,C#,Linq,Try Catch,Anonymous Types,我知道不允许将非ymous类型设置为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

我知道不允许将非ymous类型设置为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)

对于如此简单的事情,并且由于您
在异常时返回
,您应该能够在
try
块中执行所有操作,而不必在其外部声明
产品

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,但您不应该接受异常并像那样返回。

不是匿名类型不能为null,而是
IEnumerable
(或IQueryable)在迭代之后不能为null

您可以使用
产品??Enumerable.Empty()
将null替换为空的
IEnumerable


不要接受这样的例外情况。捕获
异常
基类只在非常特定的场景中是个好主意,而您的不是其中之一。

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

您可以通过反射来实现:

IEnumerable<object> products = null;

// ...

var anon = products.FirstOrDefault();
Console.WriteLine(anon.GetType().GetProperty("ProductName").GetValue(anon, null));
IEnumerable 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);
IEnumerable products=null;
// ...
var anon=products.FirstOrDefault();
Console.WriteLine(anon.ProductName);

没有简单的方法可以解决这个问题。您可以选择更改控制流以将整个内容包装在
try{}
块中(在本例中很简单,但为了说明起见,我假设此代码已简化),或者声明一个具体类型,例如

class ProductWithName
{
    public int Product;
    public string ProductName;
}
然后使用

List<ProductWithName> products = null;

这是最好的选择,这取决于你的真实代码是什么样子。

< P>我同意你应该考虑重构这个代码或使用名义类型而不是匿名类型的其他答案。

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

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

这种伎俩被称为“以身作则”,虽然很奇怪,但却是合法的

new Nullable()
将很好地完成任务。

由于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(); }
var productsDB=new List(){()=>“苹果”、“梨”、“香蕉”};//,()=>{抛出新的NotImplementedException();}};//抱歉,想不出更好的方法在2分钟内使此失败。。
var乘积=(
来自productsDB中的p
选择新的
{
Name=p()
} );
尝试
{
products.ToList();//运行LINQ查询
products.Dump();//打印结果(LINQPad)
}
catch{“出现错误”。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...
var productsDB=new[]{“苹果”、“梨”、“班纳纳斯”};
列出产品清单;
尝试
{
产品=(
来自productsDB中的p
选择Tuple.Create(p)).ToList();
Dump();
}
catch{“出现错误”。Dump();}
//如有必要,从此处的(只读)元组生成匿名类型。。。

编辑:刚刚意识到我看错了帖子: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();
var员工=(
来自db.DenormalizedPeople中的person
其中person.Type==“employee”
选择新的
{
name=employee.FullName,
areaID=new Nullable(),//占位符..在将来的查询中设置
})。ToList();

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

你说得对,代码被大大简化了,我自己也想到了这个解决方案。然而,我想避免仅仅为了这个而创建一个新类。但这是可行的。这很酷,虽然还没有测试过,但似乎是合法的。但是由于性能原因,在这种情况下不能使用此选项。
dynamic
的性能特征可能会影响性能。我认为这需要一个专用的产品类,这是我想要避免的。我的代码非常简单,所以我理解您为什么选择产品类方法。是的,确实如此。代码被简化了,我认为这已经足够清楚了。。但无论如何还是要谢谢你。但是它考虑了编译器的内部知识,这对于其他编译器或编译器的未来版本来说可能不是真的。(当然,您可以为Microsoft C#编译器实现此功能……)或。。。它在规范中的某个地方吗?它会在不同的集会中起作用吗?@Jordão:我不会跟着你的。它如何考虑编译器的内部知识?这是合法的,任何符合要求的实现都需要有这种行为。为什么您认为这是实现定义的行为?“它能跨程序集工作吗?”是什么意思?我不明白你的问题中“跨程序工作”是什么意思。@Jordão:如果你说的“跨程序集工作”是指两个程序集中有两个方法,它们都返回匿名类型的“相同”对象,你能将它们视为同一类型吗,然后是否定的。C#规范规定匿名类型只能保证在一次编译中统一。是的,这就是我的意思。感谢规范中提到类型是统一的,这就是我想知道的。我以前就知道这项技术,只是我不知道它有多正式+1.@Jordão:见C#4规范第7.6.10.6节。在同一程序中,两个匿名对象初始值设定项以相同顺序指定相同名称和编译时类型的属性序列,将生成相同匿名类型的实例
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();