Conflicting types

S

Steve Ricketts

I'm getting the following warning(s) in a program, VC.net.

The type 'CADELibrary.CADEmain' in 'D:\Data\CADE.net\CADEmain.cs' conflicts
with the imported type 'CADELibrary.CADEmain' in
'd:\Data\CADE.net\Record\dlRecordCS\dlRecordCS\bin\Debug\dlRecordCS.dll'.
Using the type defined in 'D:\Data\CADE.net\CADEmain.cs'.

VC.net contains a reference to dlRecordCS which is a C# .dll.

Both programs contain a "link" to CADEmain.cs which is in a common directory
(d:\data\CADE.net) and used by both (as well as many other) programs:

CADEmain.cs

Namespace CADELibrary
public class CADEmain
{
...

Program VC.net
using CADELibrary
...
CADEmain.GetCommonValues();

..DLL dlRecordCS
using CADELibrary
...
CADEmain.GetCommonValues();

Although the program compiles and runs fine, I would feel better if I didn't
have the warnings. How do I resolve this?

Thanks,

Steve
 
P

Peter Duniho

Steve said:
I'm getting the following warning(s) in a program, VC.net.

The type 'CADELibrary.CADEmain' in 'D:\Data\CADE.net\CADEmain.cs'
conflicts with the imported type 'CADELibrary.CADEmain' in
'd:\Data\CADE.net\Record\dlRecordCS\dlRecordCS\bin\Debug\dlRecordCS.dll'.
Using the type defined in 'D:\Data\CADE.net\CADEmain.cs'.

What do you mean by "in a program, VC.net"? Are you trying to compile a
program with that name, and getting the error? Or is the program
"VC.net" (whatever that might be) itself generating the error? Or
something else entirely?
VC.net contains a reference to dlRecordCS which is a C# .dll.

Both programs contain a "link" to CADEmain.cs which is in a common
directory (d:\data\CADE.net) and used by both (as well as many other)
programs:

What do you mean by "contain a 'link'"? Normally, you don't link to .cs
files. You compile .cs files into an assembly (.exe or .dll) and then
reference the assembly.

And what do you mean by "both programs"? I only see a mention of one
program in your post, "VC.net". What other program are you talking about?
CADEmain.cs

Namespace CADELibrary
public class CADEmain
{
...

Program VC.net
using CADELibrary
...
CADEmain.GetCommonValues();

..DLL dlRecordCS
using CADELibrary
...
CADEmain.GetCommonValues();

Although the program compiles and runs fine, I would feel better if I
didn't have the warnings. How do I resolve this?

It's not possible to suggest a precise fix without a a more precise
description of the problem and a concise-but-complete code example that
reliably reproduces the problem. But, I doubt the error is spurious.
So whatever the fix, it will involve tracking down why you have defined
a type with the same name in two different places, and eliminating the
definition in at least one of the places.

Based on your description (which frankly, is vague), I think it's
_possible_ that you are compiling a single .cs file into two different
assemblies, and then trying to reference one of those assemblies from
the other. Of course, having compiled the same .cs file twice, you get
two different definitions of the same type (and all types in the file,
for that matter). Sharing the same .cs file between multiple projects
is usually not the right thing to do, and it's definitely not the right
thing to do if one of those projects depends on the other.

But if that doesn't seem to apply to your question, you need to post a
less ambiguous question.

Pete
 
S

Steve Ricketts

What do you mean by "in a program, VC.net"? Are you trying to compile a
program with that name, and getting the error? Or is the program "VC.net"
(whatever that might be) itself generating the error? Or something else
entirely?

The name of the .exe is VC.net
What do you mean by "contain a 'link'"? Normally, you don't link to .cs
files. You compile .cs files into an assembly (.exe or .dll) and then
reference the assembly.

SR: I added a reference to each file but rather than just clicking [Add] on
an existing item, I used the pull-down menu and added them as a link by
clicking "Add As Link". That way I have only one version of the .cs file
included in the source and then compile into an .exe or .dll.
And what do you mean by "both programs"? I only see a mention of one
program in your post, "VC.net". What other program are you talking about?

SR: One program (VC.net) and one .dll (dlRecordCS.dll).
Based on your description (which frankly, is vague), I think it's
_possible_ that you are compiling a single .cs file into two different
assemblies, and then trying to reference one of those assemblies from the
other. Of course, having compiled the same .cs file twice, you get two
different definitions of the same type (and all types in the file, for
that matter). Sharing the same .cs file between multiple projects is
usually not the right thing to do, and it's definitely not the right thing
to do if one of those projects depends on the other.

SR: You are correct, I'm compiling a .cs into two different assemblies. I
use the methods in CADELibrary.CADEmain in virtually every program I'm
writing. Since I'm currently developing a number of new programs, I'm
adding new functions to CADEmain all the time. It was very convenient to
link to the .cs and any modification I made was available in all other
programs. So, what is the acceptable approach to including a common set of
utility functions into the source code?

sr
 
P

Peter Duniho

Steve said:
What do you mean by "in a program, VC.net"? Are you trying to compile a

The name of the .exe is VC.net

That doesn't answer the question I asked. It simply reiterates what you
wrote before.
[...]
SR: You are correct, I'm compiling a .cs into two different assemblies.

Don't do that.
I use the methods in CADELibrary.CADEmain in virtually every program I'm
writing. Since I'm currently developing a number of new programs, I'm
adding new functions to CADEmain all the time. It was very convenient
to link to the .cs and any modification I made was available in all
other programs. So, what is the acceptable approach to including a
common set of utility functions into the source code?

Don't. There's no "acceptable approach" to that, and especially when
one project compiling the source file is referenced by another project
compiling that same source file.

Instead, put shared code into a DLL assembly that is referenced by any
other assembly in which you want to use that code.

Pete
 
S

Steve Ricketts

Are there any other approaches besides putting the code into a .dll? While
this might sound like a trivial thing, it's not. This is a part of a
package that will be distributed to tens of thousands of locations, many of
which have very strict controls on additional .dll's and .exe's that haven't
gone through the "approval process"... with some of the customers that we
have, that approval process can take over a year. I am able to replace an
..exe with relatively little trouble, but telling them there's another .dll
that has to be distributed to each location is a whole different issue.

sr

Peter Duniho said:
Steve said:
What do you mean by "in a program, VC.net"? Are you trying to compile a

The name of the .exe is VC.net

That doesn't answer the question I asked. It simply reiterates what you
wrote before.
[...]
SR: You are correct, I'm compiling a .cs into two different assemblies.

Don't do that.
I use the methods in CADELibrary.CADEmain in virtually every program I'm
writing. Since I'm currently developing a number of new programs, I'm
adding new functions to CADEmain all the time. It was very convenient to
link to the .cs and any modification I made was available in all other
programs. So, what is the acceptable approach to including a common set
of utility functions into the source code?

Don't. There's no "acceptable approach" to that, and especially when one
project compiling the source file is referenced by another project
compiling that same source file.

Instead, put shared code into a DLL assembly that is referenced by any
other assembly in which you want to use that code.

Pete
 
F

Family Tree Mike

Are there any other approaches besides putting the code into a .dll?
While this might sound like a trivial thing, it's not. This is a part of
a package that will be distributed to tens of thousands of locations,
many of which have very strict controls on additional .dll's and .exe's
that haven't gone through the "approval process"... with some of the
customers that we have, that approval process can take over a year. I am
able to replace an .exe with relatively little trouble, but telling them
there's another .dll that has to be distributed to each location is a
whole different issue.

sr

It appears to me from the messages that you are getting, you have
CADEmain.cs in both your executable, and in the dll that is linked to
your executable. From your last post, it seems like you did not intend
to link to the dll, or that the class belongs only in the executable.

I have the feeling I'm missing part of the story...
 
S

Steve Ricketts

Could be just me... in a constant state of confusion these days! ;-)

Correct, I do have a link to CADEmain.cs in the source code for both the
..exe and the .dll (dlRecordCS). I reference the dlRecord.dll from the .exe
(actually three .dll's but the problem is the same). The confusion is
probably from my reply to Pete where he suggested that I compile CADEmain
into its own .dll and reference that .dll from anything that uses the
CADEmain methods. It's that one, for example a CADEmain.dll, that I don't
want to create and distribute with the code.

sr
 
P

Peter Duniho

Steve said:
Are there any other approaches besides putting the code into a .dll?
While this might sound like a trivial thing, it's not. This is a part
of a package that will be distributed to tens of thousands of locations,
many of which have very strict controls on additional .dll's and .exe's
that haven't gone through the "approval process"... with some of the
customers that we have, that approval process can take over a year. I
am able to replace an ..exe with relatively little trouble, but telling
them there's another .dll that has to be distributed to each location is
a whole different issue.

If you're still willing to deal with the maintenance headache, you can
simply ensure that the shared .cs file is compiled into only one
_existing_ DLL shared among your various projects. The main problem
with that approach is that, if there is no one single DLL shared by
_all_ the projects, then you'll have to find multiple DLLs where the
code can be hosted, and at the same time ensure that no two DLLs hosting
the code are referenced by the same project.

Doing it that way, you'll find yourself having to maintain some kind of
matrix that tells you which DLLs go with which projects, and figuring
out which DLLs provide complete coverage among all the projects that
want the features in that .cs file, without winding up with two or more
of those DLLs actually being used in the same project.

That will be difficult enough if the DLLs involved are used only in EXE
projects. But if for some reason you have DLLs referencing DLLs where
the DLLs that have to define the type are involved, that will only
complicate the matrix further.

If you can find a single DLL that every project needing the type will
reference, then it's simple: just put the type into that DLL. No
maintenance headache, and no problem with adding new DLLs to your
deployment.

Also, I have to insert my editorial comment here: the requirement
stipulated by whatever approval process you're dealing with is, frankly,
idiotic. If you are permitted to deploy a new version of a DLL, that is
no different at all from deploying a new DLL. IMHO you should of course
try to keep your code modules simple, but manageable, such that you
don't have a plethora of DLLs.

But on the other hand, when you have code that is shared, it belongs in
a DLL and should be shared via that DLL. Subjecting yourself to
additional maintenance overhead so that some arbitrary and pointless
approval process requirement is satisfied is a very poor use of resources.

Pete
 
S

Steve Ricketts

If you can find a single DLL that every project needing the type will
reference, then it's simple: just put the type into that DLL. No
maintenance headache, and no problem with adding new DLLs to your
deployment.

SR: Ah, interesting... use one of the dll's already deployed.... that
should work.
Also, I have to insert my editorial comment here: the requirement
stipulated by whatever approval process you're dealing with is, frankly,
idiotic. If you are permitted to deploy a new version of a DLL, that is
no different at all from deploying a new DLL. IMHO you should of course
try to keep your code modules simple, but manageable, such that you don't
have a plethora of DLLs.

But on the other hand, when you have code that is shared, it belongs in a
DLL and should be shared via that DLL. Subjecting yourself to additional
maintenance overhead so that some arbitrary and pointless approval process
requirement is satisfied is a very poor use of resources.

SR: LOL... I couldn't agree more. However, did I say "customer" approval
process? Should have said very, very large and important customer approval
process. ;-) Idiotic or not, "them's" the rules and we have to follow or
go away!

So, we have a workable solution, using an existing .dll, but I'm surprised
that there isn't a way to include common source code in multiple programs.
In my VB, Java, and Flex programs, I've typically had modules or libraries
for different kinds of tasks (file transfer, USB communication, database
access, etc.) and only included them when needed for the specific program
being developed.
 
P

Peter Duniho

Steve said:
[...]
So, we have a workable solution, using an existing .dll, but I'm
surprised that there isn't a way to include common source code in
multiple programs. In my VB, Java, and Flex programs, I've typically had
modules or libraries for different kinds of tasks (file transfer, USB
communication, database access, etc.) and only included them when needed
for the specific program being developed.

Be sure you are comparing apples-to-apples. Even in C#, you can get
away with compiling into a given module different source files according
to your needs. It's when you do that in multiple modules that all are
shared within a single program that you run into trouble.

Conversely, even in other languages, using compilation as your
code-sharing approach rather than having sharable libraries (static or
dynamic) is at a minimum a poor choice, and in the worst case can lead
to similar problems to what you see in C#. I don't know specifically
about Flex or VB, but for sure in C/C++ and Java you would have similar
issues that you're seeing here (in Java, they are almost identical,
because the type system is stronger, like in .NET).

In some languages – C/C++ for example, and for all I know VB (but _not_
VB.NET) – declared simple types are merely descriptors of memory layout.
You can safely redeclare a given type over and over without any problem.

But in .NET (and Java), types are full-fledged citizens within the
program, requiring each type to be unique within a given program. You
can't declare a type with the same name in two different modules that
will be shared in a single program without some kind of ambiguity
resolution, because the run-time needs to know which implementation of a
type to use, and that implementation has to be consistent across the
entire program.

Even in C++, if the type has implementation (i.e. functions, especially
non-inlined ones), then you'll run into duplicate function names and
have the same problem. The linker will resolve the duplicates on a
function-by-function basis rather than for the whole type at once, but
it's still an issue. And worse, if the layout of the type's data
members isn't the same between the two implementations that were
included, any time an instance of the type is created in one place and
then used in a different place using the other implementation, that will
be a serious problem.

And even in languages where you can get away with that sort of thing,
it's not because the language is inherently immune to the issue. At
best, it's because the language is failing to warn you that something
dangerous may be going on.

Having the same type declared in two different source files used in the
same program means that it's possible for the two different declarations
of the type to have different implementations. I would be surprised to
find any system that didn't resolve the ambiguity by picking one
implementation or the other (mixing two implementations could obviously
be catastrophic). But even picking one implementation without warning
you means that you could have a serious bug in your code without even
realizing it, because your code is using a different implementation for
a type than you thought it was.

In your particular example, you are literally including the same source
file. You could safely get away with ignoring the warning, because you
know yourself that the implementations will be identical. But at the
point in time when the linker is pulling the different implementations
together, it has no practical way to know that the implementations are
the same. Even if it tracked the source file, the two assemblies in
which the type is being declared need not have been compiled using the
same version of the given source file, and of course the source file
information is in the PDB file, not the assembly itself, and may not
even be present.

So, the compiler warns you. And that's a really good thing. If you are
using other languages that don't warn you about this kind of problem,
you're working without a net. Don't be surprised if at some point you
fall and crack open your head. :)

Frankly, for me the bottom line is this: if you are sharing code, the
proper way to do it is through compiled libraries, not by recompiling
the same code over and over.

Pete
 
J

Jesse Houwing

Steve,

Just to add a few other options you might want to consider

There is one solution that would make this scenario work... Mark the
CADEMain class internal, that way the CADEMain from one assembly should
be invisible to the other assembly.

I don't think it's the best idea, normally I'd reference a common
assembly to use standard functionality in multiple parts of my program.

Another solution would be to use something like Xenocode Postbuild .NET.
It allows you to merge all or part of your application into single
files. So just reference the separate assembly, but before creating a
deployment package for your customers, just merge the whole application
into one assembly and deploy that. Postbuild even allows you to include
the framework assemblies and the framework bootstrapper, so that you
executable would work on a system that does not have the CLR installed.

Jesse


* Steve Ricketts wrote, On 18-1-2010 23:58:
 
S

Steve Ricketts

Thanks, Jesse. I'll look into both.

sr

Jesse Houwing said:
Steve,

Just to add a few other options you might want to consider

There is one solution that would make this scenario work... Mark the
CADEMain class internal, that way the CADEMain from one assembly should be
invisible to the other assembly.

I don't think it's the best idea, normally I'd reference a common assembly
to use standard functionality in multiple parts of my program.

Another solution would be to use something like Xenocode Postbuild .NET.
It allows you to merge all or part of your application into single files.
So just reference the separate assembly, but before creating a deployment
package for your customers, just merge the whole application into one
assembly and deploy that. Postbuild even allows you to include the
framework assemblies and the framework bootstrapper, so that you
executable would work on a system that does not have the CLR installed.

Jesse


* Steve Ricketts wrote, On 18-1-2010 23:58:
 
S

Steve Ricketts

Thanks for the very thorough description. I just may have to go the
compiled library direction.

sr

Peter Duniho said:
Steve said:
[...]
So, we have a workable solution, using an existing .dll, but I'm
surprised that there isn't a way to include common source code in
multiple programs. In my VB, Java, and Flex programs, I've typically had
modules or libraries for different kinds of tasks (file transfer, USB
communication, database access, etc.) and only included them when needed
for the specific program being developed.

Be sure you are comparing apples-to-apples. Even in C#, you can get away
with compiling into a given module different source files according to
your needs. It's when you do that in multiple modules that all are shared
within a single program that you run into trouble.

Conversely, even in other languages, using compilation as your
code-sharing approach rather than having sharable libraries (static or
dynamic) is at a minimum a poor choice, and in the worst case can lead to
similar problems to what you see in C#. I don't know specifically about
Flex or VB, but for sure in C/C++ and Java you would have similar issues
that you're seeing here (in Java, they are almost identical, because the
type system is stronger, like in .NET).

In some languages – C/C++ for example, and for all I know VB (but _not_
VB.NET) – declared simple types are merely descriptors of memory layout.
You can safely redeclare a given type over and over without any problem.

But in .NET (and Java), types are full-fledged citizens within the
program, requiring each type to be unique within a given program. You
can't declare a type with the same name in two different modules that will
be shared in a single program without some kind of ambiguity resolution,
because the run-time needs to know which implementation of a type to use,
and that implementation has to be consistent across the entire program.

Even in C++, if the type has implementation (i.e. functions, especially
non-inlined ones), then you'll run into duplicate function names and have
the same problem. The linker will resolve the duplicates on a
function-by-function basis rather than for the whole type at once, but
it's still an issue. And worse, if the layout of the type's data members
isn't the same between the two implementations that were included, any
time an instance of the type is created in one place and then used in a
different place using the other implementation, that will be a serious
problem.

And even in languages where you can get away with that sort of thing, it's
not because the language is inherently immune to the issue. At best, it's
because the language is failing to warn you that something dangerous may
be going on.

Having the same type declared in two different source files used in the
same program means that it's possible for the two different declarations
of the type to have different implementations. I would be surprised to
find any system that didn't resolve the ambiguity by picking one
implementation or the other (mixing two implementations could obviously be
catastrophic). But even picking one implementation without warning you
means that you could have a serious bug in your code without even
realizing it, because your code is using a different implementation for a
type than you thought it was.

In your particular example, you are literally including the same source
file. You could safely get away with ignoring the warning, because you
know yourself that the implementations will be identical. But at the
point in time when the linker is pulling the different implementations
together, it has no practical way to know that the implementations are the
same. Even if it tracked the source file, the two assemblies in which the
type is being declared need not have been compiled using the same version
of the given source file, and of course the source file information is in
the PDB file, not the assembly itself, and may not even be present.

So, the compiler warns you. And that's a really good thing. If you are
using other languages that don't warn you about this kind of problem,
you're working without a net. Don't be surprised if at some point you
fall and crack open your head. :)

Frankly, for me the bottom line is this: if you are sharing code, the
proper way to do it is through compiled libraries, not by recompiling the
same code over and over.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top