Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用子类型限制创建linq表达式_Linq_C# 4.0_Linq To Objects - Fatal编程技术网

使用子类型限制创建linq表达式

使用子类型限制创建linq表达式,linq,c#-4.0,linq-to-objects,Linq,C# 4.0,Linq To Objects,我有一个类型为IEnumerable的列表,我试图为它创建一个额外的where子句来检索列表中的特定项。特定值仅存在于子类型MyFirstType和MySecondType上。不在MyBaseType上 有没有可能创建一个类似于 MyList.Where(b => (b is MyFirstType || (b is MySecondType)) && b.SpecificValue == message.SpecificValue); 由于b的类型为MyBaseType

我有一个类型为
IEnumerable
的列表,我试图为它创建一个额外的where子句来检索列表中的特定项。特定值仅存在于子类型MyFirstType和MySecondType上。不在MyBaseType上

有没有可能创建一个类似于

MyList.Where(b => (b is MyFirstType || (b is MySecondType)) && b.SpecificValue == message.SpecificValue);
由于b的类型为MyBaseType,且不存在SpecificValue,因此上述操作不起作用。还要注意的是,我有另一个子类型MyThirdType,这两个类型都没有SpecificValue

我的工作是做我想要的是

foreach (dynamic u in MyList)
{
    if (u is MyFirstType || u is MySecondType)
    {
        if (u.SpecificValue == message.SpecificValue)
        {
            //Extracted code goes here
            break;
        }
    }
}

有人知道如何为上述场景创建linq表达式吗?

将代码直接翻译成linq where子句是

string messageValue = "foo";
var result = baseList.Where(item =>
{
    dynamic c = item;
    if(item is MyFirstType || item is MySecondType)
    {
        if( c.SpecificValue == messageValue)
            return true;
    }
    return false;
});
这将需要通过使用dynamic测试类的类型,所以您可以直接将项转换为
MyFirstType
MySecondType

另一种方法是使用反射来检查属性是否存在,使用这种方法,您不依赖于项目的实际类型,只要它们具有您感兴趣的属性:

string messageValue = "foo";
var result = baseList.Where( item => 
    {
        var prop =  item.GetType().GetProperty("SpecificValue");
        if (prop != null && prop.GetValue(item, null) == messageValue)
            return true;
        else return false;
    });
如果修改类层次结构是一个选项,则可以让您
MyFirstType
MySecondType
实现一个保存属性的接口,然后您可以在Linq查询中使用
OfType()

interface ISpecific
{
    string SpecificValue { get; set; }
}
class MyFirstType : MyBase, ISpecific
{
    public string SpecificValue { get; set; }
}
...
string messageValue = "foo";
var result = baseList.OfType<ISpecific>()
                     .Where(item => item.SpecificValue == messageValue);
接口是特定的
{
字符串特定值{get;set;}
}
类MyFirstType:MyBase,IsSpecific
{
公共字符串SpecificValue{get;set;}
}
...
字符串messageValue=“foo”;
var result=baseList.OfType()
.其中(item=>item.SpecificValue==messageValue);

将代码直接翻译为Linq where子句

string messageValue = "foo";
var result = baseList.Where(item =>
{
    dynamic c = item;
    if(item is MyFirstType || item is MySecondType)
    {
        if( c.SpecificValue == messageValue)
            return true;
    }
    return false;
});
这将需要通过使用dynamic测试类的类型,所以您可以直接将项转换为
MyFirstType
MySecondType

另一种方法是使用反射来检查属性是否存在,使用这种方法,您不依赖于项目的实际类型,只要它们具有您感兴趣的属性:

string messageValue = "foo";
var result = baseList.Where( item => 
    {
        var prop =  item.GetType().GetProperty("SpecificValue");
        if (prop != null && prop.GetValue(item, null) == messageValue)
            return true;
        else return false;
    });
如果修改类层次结构是一个选项,则可以让您
MyFirstType
MySecondType
实现一个保存属性的接口,然后您可以在Linq查询中使用
OfType()

interface ISpecific
{
    string SpecificValue { get; set; }
}
class MyFirstType : MyBase, ISpecific
{
    public string SpecificValue { get; set; }
}
...
string messageValue = "foo";
var result = baseList.OfType<ISpecific>()
                     .Where(item => item.SpecificValue == messageValue);
接口是特定的
{
字符串特定值{get;set;}
}
类MyFirstType:MyBase,IsSpecific
{
公共字符串SpecificValue{get;set;}
}
...
字符串messageValue=“foo”;
var result=baseList.OfType()
.其中(item=>item.SpecificValue==messageValue);

也许有更好的解决方案,但在我看来,这可能足够有效。。。如果你不介意表演的话

那么,首先声明一个接口:

public interface IMySpecialType
{
   object SpecificValue {get; set;} //you didn't specify what type this is
   //all your other relevant properties which first and second types have in common
}
public class MyFirstType : MyBaseType, IMySpecialType
{
   //snipet
}

public class MyFirstType : MySecondType, IMySpecialType
{
   //snipet
}
然后,使MyFirstType和MySecondType从此接口派生:

public interface IMySpecialType
{
   object SpecificValue {get; set;} //you didn't specify what type this is
   //all your other relevant properties which first and second types have in common
}
public class MyFirstType : MyBaseType, IMySpecialType
{
   //snipet
}

public class MyFirstType : MySecondType, IMySpecialType
{
   //snipet
}
然后,过滤并转换:

MyList
    .Where(b => (b is MyFirstType) || (b is MySecondType))
    .Cast<IMySpecialType>()
    .Where(b => b.SpecificValue == message.SpecificValue);
    //do something
MyList
。其中(b=>(b是MyFirstType)| |(b是MySecondType))
.Cast()
.其中(b=>b.SpecificValue==message.SpecificValue);
//做点什么

也许有更好的解决方案,但在我看来,这可能足够有效。。。如果你不介意表演的话

那么,首先声明一个接口:

public interface IMySpecialType
{
   object SpecificValue {get; set;} //you didn't specify what type this is
   //all your other relevant properties which first and second types have in common
}
public class MyFirstType : MyBaseType, IMySpecialType
{
   //snipet
}

public class MyFirstType : MySecondType, IMySpecialType
{
   //snipet
}
然后,使MyFirstType和MySecondType从此接口派生:

public interface IMySpecialType
{
   object SpecificValue {get; set;} //you didn't specify what type this is
   //all your other relevant properties which first and second types have in common
}
public class MyFirstType : MyBaseType, IMySpecialType
{
   //snipet
}

public class MyFirstType : MySecondType, IMySpecialType
{
   //snipet
}
然后,过滤并转换:

MyList
    .Where(b => (b is MyFirstType) || (b is MySecondType))
    .Cast<IMySpecialType>()
    .Where(b => b.SpecificValue == message.SpecificValue);
    //do something
MyList
。其中(b=>(b是MyFirstType)| |(b是MySecondType))
.Cast()
.其中(b=>b.SpecificValue==message.SpecificValue);
//做点什么

更简单的方法是创建一个接口来标记所有具有此属性的类SpecificValue。然后是一个儿童游戏:

    static void Main(string[] args)
    {
        List<MyBaseType> MyList = new List<MyBaseType>();
        ISpecificValue message = new MyFirstType();
        MyList.OfType<ISpecificValue>().Where(b => b.SpecificValue == message.SpecificValue);
    }
}

class MyBaseType { }
interface ISpecificValue { string SpecificValue { get; set; } }
class MyFirstType : MyBaseType, ISpecificValue
{
    public string SpecificValue;
}
class MySecondType : MyBaseType, ISpecificValue
{
    public string SpecificValue;
}
static void Main(字符串[]args)
{
List MyList=新列表();
isSpecificValue消息=新的MyFirstType();
MyList.OfType()。其中(b=>b.SpecificValue==message.SpecificValue);
}
}
类MyBaseType{}
接口isSpecificValue{string SpecificValue{get;set;}}
类MyFirstType:MyBaseType,isSpecificValue
{
公共字符串特定值;
}
类MySecondType:MyBaseType,isSpecificValue
{
公共字符串特定值;
}

更简单的方法是创建一个接口来标记所有具有此属性的类SpecificValue。然后是一个儿童游戏:

    static void Main(string[] args)
    {
        List<MyBaseType> MyList = new List<MyBaseType>();
        ISpecificValue message = new MyFirstType();
        MyList.OfType<ISpecificValue>().Where(b => b.SpecificValue == message.SpecificValue);
    }
}

class MyBaseType { }
interface ISpecificValue { string SpecificValue { get; set; } }
class MyFirstType : MyBaseType, ISpecificValue
{
    public string SpecificValue;
}
class MySecondType : MyBaseType, ISpecificValue
{
    public string SpecificValue;
}
static void Main(字符串[]args)
{
List MyList=新列表();
isSpecificValue消息=新的MyFirstType();
MyList.OfType()。其中(b=>b.SpecificValue==message.SpecificValue);
}
}
类MyBaseType{}
接口isSpecificValue{string SpecificValue{get;set;}}
类MyFirstType:MyBaseType,isSpecificValue
{
公共字符串特定值;
}
类MySecondType:MyBaseType,isSpecificValue
{
公共字符串特定值;
}

我实际上选择了第一个版本的dynamic。谢谢实际上,我倾向于使用dynamic的第一个版本。谢谢哎呀!我没有注意到弗朗西斯科的类似回答。我更喜欢我的,因为内置的
类型
对我来说似乎比
Where
Cast
的奇怪组合更优雅,其中实现类型
MyFirstType
MySecondType
是硬编码的。注意到你的答案与Francisco类似。是的,它确实很简单,但我不想再介绍另一个界面。我非常尊重这个愿望。尽管如此,我还是会毫不犹豫地这么做。整个.Net框架就是这样构思的:尽可能抽象,接口而不是类。。。创建这个新的单行程序接口的成本可以忽略不计,接口的用途也不难理解(因为有一个不言自明的名称),而且它还提高了代码的可维护性。如果将来会出现具有SpecificValue属性的其他类,则不必修改代码来硬编码这个新类