如何对自定义对象隐式地强制转换LINQ查询的结果
本文关键字:转换 LINQ 查询 结果 自定义 对象 | 更新日期: 2023-09-27 18:08:26
我正在处理一个使用大量自定义类的项目,每个类都有效地表示来自数据库的一行数据。当有不止一个数据元素时我就会这样做:
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;
}
}
这工作得很好,但恕我直言,必须在代码的其他地方像这样声明这个列表是丑陋的。我至少要在100个不同的地方使用它。我想通过创建一个自定义类来简单地表示该List,并使用一个有意义的名称来清理它。我的意思是这样的:
public class Clients : List<Client> { }
现在可以工作了,但是LINQ查询的结果不会隐式地强制转换给它。请耐心听我说。如果新代码看起来像这样…
public class QueryClients
{
private Clients _clients;
public QueryClients(Clients clients)
{
_clients = clients;
}
public Clients FindClientByRevenue(double minimumRevenue)
{
Clients 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?)
好了,好了,所以我可以通过显式转换LINQ查询的结果来消除IDE中的编译器错误:
public class QueryClients
{
private Clients _clients;
public QueryClients(Clients clients)
{
_clients = clients;
}
public Clients FindClientByRevenue(double minimumRevenue)
{
Clients returnValue = (Clients)(from c in _clients
where c.AnnualRevenue >= minimumRevenue
select c).ToList();
return returnValue;
}
}
代码甚至可以很好地编译。但是当我点击那个查询时,它就爆炸了。
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)。在我的代码中使用客户机对象,而不是一遍又一遍地声明列表变量。
2)。能够运行LINQ查询从一个Clients对象中选择一些Client对象到另一个(新的)Clients对象。
这可能吗?你能告诉我如何修改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;
}
}
:
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;
}
}
没有意义。
您期望以与List<Client>
完全相同的方式使用类型Clients
。
所以如果你继续使用List<Client>
似乎更好,List
可以有所有的好处。
警告:不要这样做,坚持使用List<Client>
,但出于教育原因,下面是答案
你有很多选择,首先是简单地让你的类作为一个构造函数参数IEnumerable<Client>
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);
另一种方法是提供显式强制转换,以实现与IList<Client>
相同的功能,但您必须更改Clients
类以不继承List<Client>
。
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();
您应该创建一个.dbml文件,该文件链接到您的数据库,您可以在该文件上添加您想要一个模型类来查询数据库的所有SQL表。这也将自动生成类,而无需编写一行代码。之后,您可以修改从数据库查询的模型实例并提交更改。不需要编写一个SQL查询来更新或删除。一切都由LINQ处理。
下面是一个很好的演练:https://msdn.microsoft.com/en-us/library/bb384428.aspx
一旦一切都设置好了,你要做的就是://创建DataContext
MyDataContext context = new MyDataContext(myConnectionString)
//查询一些客户端-客户端类将由LINQ自动生成
列表& lt;Client> clients = (from Client in context)select client).ToList()
//修改客户端//向数据上下文提交更改(将自动从该数据上下文更新修改过的类)
context.SubmitChanges ()
你得到一个cast异常,因为列表查询结果的动态类型是List<Client>
,而不是从它继承的客户端(当对象实际上不是'狗'时,你不能从'动物'转换为'狗')。
由于不能从基类进行任何用户定义的转换,我建议删除继承并添加隐式(或显式)强制转换:
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);
}
}
然而,这将不允许您将客户端视为枚举对象。或者,你可以用以下签名为IEnumerable<Client>
编写一个扩展方法:
public static Clients ToClientList(this IEnumerable<Client> input){
return new Clients(input);
}
作为旁注,我认为使用List<Client>
比定义自己的类更优雅,更清晰。