Strange behaviour of WPF project (class naming) - c#

I got a strange error when tried to build my project ExpertSystem in solution ExpertSystem:
Error 1 The type name 'App' does not
exist in the type
'ExpertSystem.ExpertSystem' D:\Users\Kirill\Documents\Visual
Studio
2010\Projects\ExpertSystem\ExpertSystem\obj\x86\Debug\App.g.cs 60 26 ExpertSystem
I didn't even knew that VS creates this file while building. So, I started search the problem in my last edits in code and found that problem is in my last class:
namespace ExpertSystem
{
public class ExpertSystem
{
//...
}
}
When name of class is changed to something different from ExpertSystem, project compiles without errors.
Can anyone explain, can I actually have classes in C# with the same name as namespace/project/solution? Or is this a some kind of VS/WPF bug?
Thanks.

VS generates partial class for each XAML file (not during build, but during design), in order (for instance) to declare and fill the named components as class fields.
If you want to easily read the content of the designer generated App.g.css file (associated with the App.xaml and App.xaml.cs file), go to the App.xaml.cs file and perform a "Go to Definition" on the InitializeComponent() function call in the class constructor. I don't know what lurks in your, but I would expect that the designer generated something like this (maybe not this, but the issue will be the same):
var foo = (SystemExpert.App)(Application.Current)
Which should be understood as:
var foo = (global::SystemExpert.App)(Application.Current)
Now, if you create a SystemExpert class in your SystemExpert assembly namespace, and as the App class is declared in the SystemExpert namespace too, the compiler will understand that:
var foo = (global::SystemExpert.SystemExpert.App)(Application.Current)
^^^^^^^^^^^^^^^^
the current namespace
Naming a class exactly the same way as a namespace is bad practice: it can confuse the compiler.

Can anyone explain, can I actually have classes in C# with the same name as namespace/project/solution?
Yes, you can. It's part of the C# language.
Therefore the compiler can't figure out whether the code meant to look for the ExpertSystem.ExpertSystem namespace or the ExpertSystem class in the ExpertSystem namespace. (Well it can, but it got it wrong.)

To complement BoltClock's answer with a solution that will work while keeping the namespace and class names as they are:
The error is reported in a file named App.g.cs, which is generated by the compiler. Thus, fixing the issue in that file will not help, as the file will be overwritten with the error upon the next compilation (or rewritten once you have copied the code to another machine).
However, you can change the App.xaml file, from which App.g.cs is generated. The root element of the file will start with something like
<Application x:Class="ExpertSystem.App"
In there, the namespace ExpertSystem is supposed to be found, but with the class having the same name, the compiler assumes that App is a member or a nested type in your class ExpertSystem.ExpertSystem.
By pondering about this, you will realize that the compiler first tries to evaluate the value of the x:Class attribute relatively to the ExpertSystem namespace for some reason. This behaviour is responsible for your problem, but as we now know the specifics of the behaviour, we can write the code accordingly - with an identifier that is qualified relatively to the namespace ExpertSystem:
<Application x:Class="App"
After this change, it should compile fine, even if both the namespace and the class are named ExpertSystem.

Related

Is it possible to reference existing source files in C# Roslyn Code Generation?

So consider the case where I have a class ClassA inside of the project that is currently being generated into:
public class ClassA
{
public ClassA(int a)
{
A = a;
}
public int A { get; set; }
}
Let's say that I wanted to automatically create an extension method for ClassA, something like:
public static class ClassAExtensions
{
public static ClassA Double(this ClassA classA)
{
return new ClassA(classA.A * 2);
}
}
When trying to create this source code using the new source code generators, the compilation can't seem to find ClassA. I've tried adding the namespace of ClassA into the generated document and setting the namespace of the generated extension method class to the namespace directly to that of ClassA, but neither seem to be able to see it:
The type of namespace 'ClassA' does not exist in the namespace 'ClassANamespace' (are you missing an assembly reference?)
So the final questions are:
Is there some trick to making the code generation compiler be able to see my non-generated code?
Is this even possible right now?
Is there a workaround to get something like this to work?
Many of the samples provided declare the class being modified partial, but I don't particularly like this for what I'm trying to do.
I've also looked into adding an assembly reference, though my understanding was that the code being generated should be included and compiled alongside the existing code. Also, if this code is being compiled before my "production" code, then adding an assembly reference would not be possible and/or this would create a circular reference.
Files added in a source generator act like regular files from the perspective of the rest of the language rules so yes you can absolutely reference classes in the user's code as long as you're qualifying them correctly. It sounds like you have a bug; if there's still a specific problem you may want to try creating a project that contains both the input file and also the source generated output; you should see the same error and then can figure out what's up.

are you missing a using directive or an assembly reference

I can't figure out this error in visual c#.
Error 1
'Engine.VerticalMenu' does not contain a definition for '_buttons' and no extension method '_buttons' accepting a first argument of type 'Engine.VerticalMenu' could be found
(are you missing a using directive or an assembly reference?)
For this line:
System.Diagnostics.Debug.Assert(false, _menu._buttons.Count.ToString());
I have two projects, first one is Engine with same namespace Engine and of type class library, and the other one is windows form app that uses this Engine library. I have both using directives and references to project, what could possibly be causing this? Thank you.
Looks like _buttons is private class member, so you can't access it from the outside.
Either make it public, or even better add public getter to the class of _menu:
public TypeOfButtonCollectionHere Buttons { get { return _buttons; } }
And change the calling code to:
System.Diagnostics.Debug.Assert(false, _menu.Buttons.Count.ToString());
Is _buttons possibly private? Then it is not visible outside of the menu class and you can't access it. Wrap it to a public property and you can access it.
It sounds like a naming conflict (namespace or class). Have you tried using the fully qualified name for the class? Without more information this is just a shot in the dark.
No, its not the public thing, vs has other errormessages for that. It looks like _menu doesn't have a member _buttons at all. So this means either the class or the interface _menu is of doesnt have _buttons.
Check that all the assemblies referenced by the project Engine is also referenced by your Win form.
It would usually give another error if that's the case but not always.
If they are all referenced. Try a rebuild of just the Engine project. VS might throw the mentioned error if there's a compilation error in a referenced project. Those errors should show up in the error log, so you could also check the error log to see if there are other errors some of which is in engine.
(Even if that's not the case I would personally still build Engine alone, to completely rule it out)

C# Project & Namespaces Question

I am creating a little Math library for myself contained within a single project and am running into some issues with namespaces. I have the project MyMathLib and the top level namespace:
namespace MyMathLib
{ ... }
and in a separate file...
namespace MyMathLib.Addition
{ ... }
and...
namespace MyMathLib.Subtraction
{ ... }
In the MyMathLib.Subtraction namespace I have a method that needs to use a static method SomeClass.Work() defined in MyMathLib.Addition so I included using MyMathLib.Addition at the beginning of the Subtraction file. But when I try to use the method it would like me to first qualify it with Addition.SomeClass.Work() and I want to be able to just type SomeClass.Work(). What am I doing wrong?
Thanks!
EDIT
Thanks for the suggestions! In each file, I actually named the class after the namespace (i.e. in the namespace MyMathLib.Addition is a static class Addition and in MyMathLib.Subtraction there is a static class Subtraction). Apparently this is what caused the issue (looking back, I should have stated this instead of using SomeClass). If I change the namespace to MyMathLib.MyAddition while keeping the static class as Addition, the using MyMathLib.MyAddition works as I want; that is, I can now just type Addition.Work() in my static Subtraction class. I've seen classes named the same as it's containing namespace before, could someone maybe explain why this is causing an issue? Shouldn't the compiler be able to determine whether I want to use the namespace or the class from the context of the code?
I'm guessing that you either have two classes called SomeClass that are both in namespaces you reference, or you have a variable or property named SomeClass. Either of these situations would make it impossible for the compiler to know that you're trying to call the static MyMathLib.Addition.SomeClass.Work() method, but the specific solution the compiler is suggesting makes it seem more likely to be the former.
Update
Seeing your edit, that makes sense. If you were using these in a namespace outside of MyMathLib, then you would still be able to avoid this namespace conflict. However, because you are inside the MyMathLib.Subtraction namespace, the compiler will implicitly consider any portion of the namespace "above" you to take precedence over class names. In this case, when you say "Addition", the compiler will look for the following items to resolve the name:
A class explicitly identified by a using ... = ... directive.
MyMathLib.Subtraction.Addition namespace.
MyMathLib.Addition namespace.
Addition namespace.
Any classes in the namespaces identified by using statements.
In this case, you're hitting #3 before #4, so you should be able to work around it either by renaming the class or namespace, or by using Yahia's suggestion (#1):
using Addition = MyMathLib.Addition.Addition;
Update 2
After looking at the article you linked to, it sounds like the explicit using statement still won't work. I guess item #1 actually gets evaluated down around item #4 instead. Bummer. You can use an alias to give the class a different name locally:
using Add = MyMathLib.Addition.Addition;
...
var add = new Add();
But the best solution is still probably just to avoid the namespace collision entirely by changing your namespace or class name.
try putting additionally the floowing line into your substraction source
using SomeClass = Addition.SomeClass;
http://msdn.microsoft.com/en-us/library/dfb3cx8s.aspx
http://www.blackwasp.co.uk/NamespaceAliasQualifier.aspx
Sounds like you're in the Subtraction namespace...add this to the top, inside the namespace declaration:
using Addition;
That should do the trick.

public variable not accessible

In one namespace (Ventosa.Graphics) I have a public class named Model
namespace Ventosa.Graphics
{
public class Model : GraphicsResource
{
public Model(...)
{
...
}
...
}
}
Then in another project I try to access this class
Model player = new Model(...);
But this line creates an error. C# recognizes that Model exists, but claims that it isn't accessible due to it's protection level. Shouldn't making it public mean it's accessible from everywhere?
And yes, the base class GraphicsResource is public.
This happens in a few other places in my project too, all with classes that are derived.
EDIT:
The exact error message is (in German):
Der Zugriff auf "Ventosa.Graphics.Model" ist aufgrund der Sicherheitsebene nicht möglich. Translated to English, it says: "Ventosa.Graphics.Model" is inaccessible due to its protection level.
You describe something that clearly should not be. I'd suggest that you try to reproduce the problem in the simplest way possible. You probably won't be able to. Then add to your sample, making it more and more like your production code, until you trigger the problem.
Remove the reference to the superclass GraphicResource. Make sure there's only one constructor defined. Try to instantiate that class from the same namespace, using full namespace references (not using statements) and that single, explicit constructor. It'll probably work.
If it doesn't work, step back a bit and define a new type entirely (Ventosa.Graphics.ModelTest or something). Make sure that works.
Now, add pieces back in. Inherit from GraphicResource, try that. Remove the namespace qualifications; use using instead. Move the instantiation to a different namespace, then a different assembly.
You've verified that the definition of the GraphicResource class is public. What about any of its superclasses?
I know this may sound silly, but have tried to restart Visual Studio (after Cleaning and Rebuilding the solution)? I noticed some strange behavior, especially if you have Code-Coverage enabled and some of the Powertools for Visual Studio installed.
Was Model internal in some previous builds? It's a really common name.
Edit: A way to make sure you actually have the right type, you can hover the "Model" declaration in your second project and press F12 (or right click and choose "Go To Definition", don't know the german term right now). This should take you to your class or to the definition of some other "Model"-class (.NET internal types are displayed too).

Namespaces, aliases and Visual Studio Forms Designer

I'm having a problem with conflicting namespaces and code that gets autogenerated by the forms designer in Visual Studio 2008. I have search many forums and different documentation, but have not been able to find any solution to this problem.
I have one assembly called Foo.dll with the following namespace/code:
namespace Foobar.System
{
public class MySystemClass() { }
}
Then, I have another assembly which contains som commonly used forms:
namespace Foobar.MyCommonForms
{
public class MyForm : System.Windows.Forms.Form
{
public void SomeMethod()
{
var systemclass = new Foobar.System.MySystemClass();
}
}
}
Here, the compilers display the following error: Type or namespace 'Windows' is not part of namespace 'Foobar.System'. Obviously, the compiler tries to look for the class System.Windows.Forms.Form in namespace Foobar.System.Windows.Forms!
I have been able to solve this by using the alias 'x' instead of 'global' when referencing to the assembly Foo.dll, and declaring 'extern alias x' in my code files, and put 'x::' in front of every reference to types and classes in the namespace Foobar.System. The code compiles.
But it seems that the forms designer don't recognise this, and gives me an error when trying to display the form. This, again, can be solved by manually putting 'global::' in front of every reference to classes in System.Windows.Forms (e.g. global::System.Windows.Forms.Button), but every time chances are made to the form, the code is automaticaly re-generated, and the 'global::' part is removed.
So, the question is: Is there a way to make the forms designer aware of the alias 'x' that is used to reference my assembly Foo.dll, or is there another, better solution to this? Renaming the namespace Foobar.System to something else is just too much work.
There's no way around this, from what I can tell.
The popular refactoring tools such as Resharper or Refactor! both include the ability to globally rename a namespace. I'd seriously consider using those.

Categories

Resources