C# 如何隐式地对自定义对象强制转换LINQ查询的结果?
我正在从事一个使用大量自定义类的项目,每个自定义类有效地表示数据库中的一行数据。当存在多个数据元素时,我一直在这样做:C# 如何隐式地对自定义对象强制转换LINQ查询的结果?,c#,linq,list,collections,casting,C#,Linq,List,Collections,Casting,我正在从事一个使用大量自定义类的项目,每个自定义类有效地表示数据库中的一行数据。当存在多个数据元素时,我一直在这样做: public class Client { private int _clientID; private double _annualRevenue; public int ClientID { get { return _clientID; } set { _clientID = value; } }
public class Client
{
private int _clientID;
private double _annualRevenue;
public int ClientID
{
get { return _clientID; }
set { _clientID = value; }
}
public double AnnualRevenue
{
get { return _annualRevenue; }
set { _annualRevenue = value; }
}
}
然后,在代码的其他地方
public class QueryClients
{
private List<Client> _clients;
public List<Client> FindClientByRevenue(double minimumRevenue)
{
List<Client> returnValue = (from c in _clients
where c.AnnualRevenue >= minimumRevenue
select c).ToList();
return returnValue;
}
}
…我得到一个编译器错误:
CS0266
Cannot implicitly convert type 'System.Collections.Generic.List<Client>' to 'Clients'. An explicit conversion exists (are you missing a cast?)
代码甚至编译得很好。但我一问这个问题,它就爆炸了
Clients clients = new Clients();
Client client;
client = new Client();
client.ClientID = 1;
client.AnnualRevenue = 100;
clients.Add(client);
client = new Client();
client.ClientID = 2;
client.AnnualRevenue = 200;
clients.Add(client);
client = new Client();
client.ClientID = 3;
client.AnnualRevenue = 300;
clients.Add(client);
QueryClients q = new QueryClients(clients);
Clients clients2 = q.FindClientByRevenue(200);
当然,这是一个铸造错误
An unhandled exception of type 'System.InvalidCastException' occurred.
Additional information: Unable to cast object of type 'System.Collections.Generic.List`1[Client]' to type 'Clients'.
因此,即使它编译,它也不会运行,即使这种方法确实有效,它也不能真正解决我的问题,因为这样我就必须显式地强制转换每个LINQ查询的结果,如果必须这样做,我还不如到处声明列表。唉
所以不管怎么说,我做错了什么,我就是不知道该怎么做。我确信,至少,我需要向我的Clients类添加一个转换/强制转换操作符,以允许隐式转换发生(或其他)。我尝试了很多不同的东西,基于无数不同的谷歌搜索,它要么无法编译,要么无法运行。我就是搞不懂
有两个目标:
1.)在我的代码中使用Clients对象,而不必反复声明列表变量
2.)能够运行LINQ查询,从一个客户机对象选择一些客户机对象到另一个(新)客户机对象
这可能吗?你能告诉我如何修改Clients类以使其工作(隐式转换)吗?如果能做到的话,我相信这很简单,我会因为自己在发布之前没有看到它而责备自己
提前感谢您提供的见解。很抱歉,我要更改以下内容:
public class QueryClients
{
private List<Client> _clients;
public List<Client> FindClientByRevenue(double minimumRevenue)
{
List<Client> returnValue = (from c in _clients
where c.AnnualRevenue >= minimumRevenue
select c).ToList();
return returnValue;
}
}
公共类查询客户端
{
私人名单客户;
公共列表FindClientByRevenue(最低收入加倍)
{
List returnValue=(来自c in_客户机
其中c.年收入>=最低收入
选择c.ToList();
返回值;
}
}
为此:
public class QueryClients
{
private Clients _clients;
public List<Client> FindClientByRevenue(double minimumRevenue)
{
Clients returnValue = (from c in _clients
where c.AnnualRevenue >= minimumRevenue
select c).ToList();
return returnValue;
}
}
公共类查询客户端
{
私人客户(u客户),;
公共列表FindClientByRevenue(最低收入加倍)
{
Clients returnValue=(来自c in_Clients
其中c.年收入>=最低收入
选择c.ToList();
返回值;
}
}
毫无意义。您希望以与
列表
完全相同的方式使用类型客户端
因此,如果您继续使用
列表
,并享受通用列表
可能带来的所有好处,似乎会更好。警告:不要这样做,坚持使用列表
,但出于教育原因,以下是答案
您有很多选择,首先是让类将
IEnumerable
另一种方法是提供一个显式强制转换,从
IList
执行大致相同的操作,但您必须将客户机
类更改为不继承列表
您会得到强制转换异常,因为列表查询结果的动态类型是
list
,而不是从中继承的客户端(当对象实际上不是“狗”时,您不能从“动物”强制转换为“狗”)
由于不能从基类进行任何用户定义的转换,我建议删除继承并添加隐式(或显式)转换:
公共类客户端{
私人名单d;
公共客户(名单d)
{
this.d=d.ToList();
}
公共静态隐式运算符客户端(列表d)
{
返回新客户(d);
}
}
但是,这不允许您将客户端视为可枚举的。或者,您可以使用以下签名将扩展方法写入IEnumerable
:
public static Clients ToClientList(this IEnumerable<Client> input){
return new Clients(input);
}
publicstaticclientstoclientlist(此IEnumerable输入){
返回新客户(输入);
}
作为旁注,我认为使用
列表
比定义自己的类更优雅、更清晰。您应该创建一个.dbml文件,该文件链接到您的数据库,您可以在该文件上添加您希望模型类查询数据库的所有SQL表。这也将自动生成类,而无需编写一行代码。之后,您可以修改从数据库查询的该模型的实例并提交更改。没有一个SQL查询需要写入以更新或删除。一切都由LINQ处理
下面是一个很好的演练:
一切设置完成后,您需要做的就是:
//创建数据上下文
MyDataContext=新的MyDataContext(myConnectionString)
//查询一些客户机-客户机类将由LINQ自动生成
Listcontext.SubmitChanges()简单:使用
List
(并在适当的情况下使用IEnumerable
)。不要把时间浪费在疯狂的特技上,以避免使用尖括号而牺牲可读性,即使你可以让它工作。你的时间花在吸食大麻上比写这段代码更有益。为什么它很难看?这只是泛型。通过习惯语法,您将获得更多里程数。就我个人而言,我宁愿知道变量是IEnumerable
而不是Clients
。尽可能使用var
。泛型的思想是减少所需的类的数量。基本上,您希望返回到.Net 1。在我看来,使用这样的类型名称可以使代码更具可读性,但我一直是疯狂特技之王。我想我已经在这上面浪费了两天了(因为这里的每个人都同意在任何地方使用括号都是answ
public class QueryClients
{
private List<Client> _clients;
public List<Client> FindClientByRevenue(double minimumRevenue)
{
List<Client> returnValue = (from c in _clients
where c.AnnualRevenue >= minimumRevenue
select c).ToList();
return returnValue;
}
}
public class QueryClients
{
private Clients _clients;
public List<Client> FindClientByRevenue(double minimumRevenue)
{
Clients returnValue = (from c in _clients
where c.AnnualRevenue >= minimumRevenue
select c).ToList();
return returnValue;
}
}
public class Clients : List<Client>
{
public Clients(IEnumerable<Client> clients)
: base(clients){}
}
Clients returnValue = new Clients(from c in _clients
where c.AnnualRevenue >= minimumRevenue
select c);
public class Clients
{
private List<Client> list;
public Clients(IEnumerable<Client> clients)
{ this.list = clients.ToList(); }
public static explicit operator Clients(List<Client> list)
{
return new Clients(list);
}
}
Clients returnValue = (Clients)(from c in _clients
where c.AnnualRevenue >= minimumRevenue
select c).ToList();
public class Clients {
private List<Client> d;
public Clients(List<Client> d)
{
this.d = d.ToList();
}
public static implicit operator Clients(List<Client> d)
{
return new Clients(d);
}
}
public static Clients ToClientList(this IEnumerable<Client> input){
return new Clients(input);
}