I have a C# .NET 2.0 project A (class library) that has a form (TreeForm) that uses Tree objects.
I have a project B that has a class Oak that inherits Tree. The class Oak adds some properties to Tree.
class Oak : ProjectA.Tree
{
public string LeafColor;
}
TreeForm.cs in the class library is a form that has a DataGrid that databinds to a BindingList of Tree objects.
When I try to reference and use the TreeForm in project B with my Oak objects, it's looking for objects of type Tree.
// in project B here.
BindingList<Oak> oaklist = BindingList<Oak>();
private void show_treeform_button_Click(object sender, EventArgs e)
{
ProjectA.TreeForm tree_form = new ProjectA.TreeForm(oaklist); // this line gives开发者_开发知识库 error
tree_form.Show();
}
I've tried casting the Oak objects to Tree, but I get the error "Cannot convert type Oak to Tree". If I just use the objects in project B as Tree objects it works fine.
How can I use my Oak objects in the TreeForm from project A?
You're going to need to post a short but complete code sample to get any meaningful help. But let me venture a guess here.
Is the second project (B) referencing the first project (A)? You have to make sure that the type Tree
is actually the same Tree type in both instances. In the example you describe - it sounds like project A actually has a reference to project B - in which case, how does B know about Tree
?
If you have the Tree
class declared in both projects - it's not the same Tree class.
One project has to reference the Tree
class of the other in order for this arrangement to work the way you expect it to.
The general way to organize such projects, is to move the shared classes into a third Class Library assembly, and reference that assembly in both project A and project B. Then you can inherit and consume the types exposed by the class library correctly.
EDIT: So now that you've posted some code, it's possible to give you a more accurate response. It looks like what you're trying to do is pass a generic list of Oak
to a method that expects a generic list of Tree
. This is not something you can do prior to .NET 4 which supports generic coveriance (on interface types BTW).
In versions of C# prior to 4, you cannot do:
List<Oak> oaklist = new List<Oak>();
List<Tree> treeList = oaklist; // illegal
Just because Oak
inherits Tree
does not mean that List<Oak>
inherits List<Tree>
.
You can read more about generic variance at Eric Lippert's blog.
So in your case, if you want to pass a list of Oaks in to TreeForm()
you need to pass it in as a list of Tree
. Assuming you don't want to change the type of the collection, you can just instantiate an appropriate copy:
ProjectA.TreeForm tree_form =
new ProjectA.TreeForm( new List<Tree>( oaklist.Cast<Tree>() ) );
The problem is that before .NET 4.0, generics did not support covariance - your TreeForm
class expects a BindingList<Tree>
, not a BindingList<Oak>
. It's a common mistake to think that we can substitute the derived binding list for the base, but we cannot.
Fortunately, we don't need to, because a BindingList<Tree>
can contain Oak
instances. The solution is to declare your variable like this:
BindingList<Tree> oakList = new BindingList<Tree>();
// Add Oaks, pass to TreeForm
(For brain-bending details, see Eric Lippert's series of articles on variance in C#.)
Don't you want to declare the list a BindingList<Tree>
then add the Oak
instances to it, then pass the BindingList<Tree>
objects to A's TreeForm
constructor. After all project A can't deal with Oak
objects as it doesn't know anything about them, they are defined in project B.
It seems that you have inherited your Oak from Tree in project B only, so Project A does not know that a Oak inherits from Tree. You should have used a Class Library and both Projects have a reference on it.
If I'm not mistaking you're trying to access your Oak (from ProjB) which is inherited from Tree (ProjA) from within ProjA?
If so, you'll end up with a circular reference (A > B > A > B > A .. etc etc) and that's a no-go.
精彩评论