Hey, so I've stumbled upon this little logistical issue. I can't find any actuall solutions to this specific use case, so I've created this simple example:
Imagine a simple sketch of a UI element in a game.
As you can imagine, this panel shows a popup that shows all the rewards and keys needed to unlock the chest.
It consists of multiple elements, and as these elements are repeated, it's a good practice to separate them. So let's say I Separate them into three different Monobehaviour classes, each having its own file.
TreasurePanelUI: The main panel element that houses references to all non-repeating UI elements.
Reward: A sub-element of the TreasurePanelUI, it houses references to its own elements (Image of the item, Text reference for the name, etc.)
Lock: A sub-element of the TreasurePanelUI, it houses references to its own elements (Image of the Lock, effects, animations of unlocking the lock, etc.)
So here comes the issue, how do we divide their namespaces? Well, here is my idea:
The dominant TreasurePanelUI may look something like this:
namespace UI //The class is a UI element.
{
public class TreasurePanelUI: MonoBehaviour
{
//Neat code...
}
}
And the other two elements may look something like this:
namespace UI.TreasurePanelUI //The class is a UI element but also part of TreasurePanelUI.
{
public class Reward: MonoBehaviour
{
//Neat code...
}
}
and
namespace UI.TreasurePanelUI //The class is a UI element but also part of TreasurePanelUI.
{
public class Lock: MonoBehaviour
{
//Neat code...
}
}
Seems logical right? Well, here's the problem: It won't compile.
This will throw a CS0101. Meaning our class name is clashing with the namespace name.
My main question is, is there an alternative way of achieving the same code topology that will actually compile?
Also, feel free to point out if my approach or my topology/method is entirely wrong! haha
I don't think you should use the same names for classes and namespaces, because (like it happened to you) they might clash.
The C# doc comes very close to discouraging what you are doing.
DO NOT use the same name for a namespace and a type in that namespace.
For example, do not use Debug as a namespace name and then also provide a class named Debug in the same namespace. Several compilers require such types to be fully qualified.
Source
I would suggest to just put all the classes in the UI.Treasures namespace.
You already got this answer when you asked this exact same question yesterday.
Your code does not run because UI.TreasurePanelUI is an ambiguous call - is it the namespace for the other classes or is it the TreasurePanelUI class?
Like I told you in your other question - just rename your TreasurePanelUI class.
If you're looking for a list of alternatives then I think that's off-topic, but you could make the other classes subclasses of your TreasurePanelUI class, like:
namespace UI //The class is a UI element.
{
public class TreasurePanelUI: MonoBehaviour
{
//Neat code...
public class Reward: MonoBehaviour
{
//Neat code...
}
public class Lock: MonoBehaviour
{
//Neat code...
}
}
}
Now you can access UI.TreasurePanelUI.Reward or whatever. If you don't want them all in the same file you can use the partial class, like:
namespace UI //The class is a UI element.
{
public partial class TreasurePanelUI: MonoBehaviour
{
//Neat code...
}
}
namespace UI //The class is a UI element.
{
public partial class TreasurePanelUI: MonoBehaviour
{
public class Reward: MonoBehaviour
{
//Neat code...
}
}
}
namespace UI //The class is a UI element.
{
public partial class TreasurePanelUI: MonoBehaviour
{
public class Lock: MonoBehaviour
{
//Neat code...
}
}
}
But really, the best thing you can do it to just change the name of your TreasurePanelUI class. If it's a base canvas or base element then you could have
namespace UI.TreasurePanelUI //The class is a UI element.
{
public class BaseCanvas: MonoBehaviour
{
//Neat code...
}
}
Related
I am trying to organize a library. My issue is that it would quickly gets very large.
This is what i have so far:
namespace MyLibrary {
namespace Math {
namespace Geometry {
public class BezierCurve {
//...
};
}
namespace Combinatorics {
}
}
namespace Collections {
}
//...
}
Its not many lines of code now, but since BezierCurve alone is around 200 lines, creating all of the classes in the above document is not going to be the way to go.
Is it possible to somehow specify the content of BezierCurve in another document and include / refer to it in the namespace Geometry?
Multiple files can declare classes in the same namespace. There is no requirement for a namespace to be fully defined within a single file.
You should have a file per class.
e.g. your BezierCurve would typically be in:
MyLibrary/Math/Geometry/BezierCurve.cs
and be declared within
namespace MyLibrary.Math.Geometry
{
public class BezierCurve
{
}
}
It's recommended to have one type per file (well, with some exceptions). Thus you will have a single namespace without all this nested structure:
namespace MyLibrary.Math.Geometry
{
public class BezierCurve
{
// ...
}
}
If you want to refer BezierCurve in another file, just add a using directive with appropriate namespace:
using MyLibrary.Math.Geometry;
namespace MyLibrary.Math.Combinatorics
{
public class SomeClassFromCombinatoricsWhichUsesBezierCurve
{
// ...
}
}
Using Unity 5.4 beta with Hololens, setting a class within a namespace disables some UnityEngine functionality.
If I declare a class, it all works fine. If I wrap it inside a namespace, classes don't see each other, even within the same namespace or with the using addition.
Making a class MonoBehaviour, I can drag and drop it onto a game object, if I wrap that class inside a namespace, Unity complains that it is not a MB or it has issue so it cannot be dragged.
Does anyone have similar issue? Just asking before reporting bugs since 5.4 is still beta.
Classes don't see each other because you are not importing them or accessing them through their namespace. To access anything in a namespace, you must import the namespace or call the namespace followed by the class name. Check below for both examples.
Class with namespace:
namespace MyANameSpace
{
public class A
{
}
}
In order to see class A, you have to import it with the using keyword.
using MyANameSpace;
public class B : MonoBehaviour
{
A a;
// Use this for initialization
void Start()
{
a = new A();
}
}
Another method is to access them directly through the namespace.
public class B : MonoBehaviour
{
MyANameSpace.A a;
// Use this for initialization
void Start()
{
a = new MyANameSpace.A();
}
}
If this does not solve your problem, then you have to post your code. That's likely not a bug.
I managed to figure out what I think is happening. Here is what I had:
namespace Company.Hololens
{
public enum GazeState
{
None = -1, NoHit, Hit
}
public class CursorEventArg : EventArgs
{
}
public class CursorController : Singleton<CursorController>
{
}
}
and it seems as if Unity does not like the order of class declaration. Pushing the EventArg down to the end of the script and it goes fine.
Not sure if this should be considered a bug, I have never seen any mention of class declaration order. Declaring an interface on top is fine though.
I have got a partial class in my C# project i.e. auto-generated code from Entity Framework. Now I want to modify or add some more functionalities, properties or methods to that class. I have the auto-generated class code under EntityFrameworkModel.tt\Author.cs tab in the project while the other related classes are in another folder i.e. GraphData in the same project.
I also know that the name of partial classes should be same while file name may be different or same as well. I did same but when I defined the object for Author.cs as:
protected override EvoObject ConvertCPV(Author _author)
{
if (_author.???)
{
//...
}
}
I can't access the methods defined in GraphData\Author.cs (The question marks in example code) whereas the properties defined in EntityFrameworkModel.tt\Author.cs are only accessible.
Here I attached the Solution Explorer image as:
How can I access the properties and methods from both classes?
I have a similar set up in a project also.
To keep things tidy I also have folders where I place certain partial classes, you just need to ensure the namespace is the same as the auto generated class.
When you add a new class to a folder the namespace will automatically contain the name of the folder - you can just remove the folder name from the namespace - you should just have the Project name in this scenario.
If the namespaces are different then the partial classes are not part of the same class. This is why you can't access the new functions/Properties.
Also, even though your file name and class names can be different, it is better to keep them the same - it will be easier to find a class if the file has the same name.
Check out https://msdn.microsoft.com/en-us/library/wa80x488.aspx
It says "The partial keyword indicates that other parts of the class, struct, or interface can be defined in the namespace." It does not explicitly state this, but that implies that the partial definitions of the class must be declared in the same namespace. It doesn't matter which files in the project contain the classes, or what folders they are in.
using System;
namespace DemoConsoleApp
{
class Program
{
static void Main(string[] args)
{
SameNamespace.PartialClass.MethodOne();
SameNamespace.PartialClass.MethodTwo();
DifferentNamespace.PartialClass.MethodThree();
}
}
}
namespace SameNamespace
{
public partial class PartialClass
{
public static void MethodOne()
{
Console.WriteLine("Method One.");
}
}
public partial class PartialClass
{
public static void MethodTwo()
{
Console.WriteLine("Method Two.");
}
}
}
namespace DifferentNamespace
{
public partial class PartialClass
{
public static void MethodThree()
{
Console.WriteLine("Method Three.");
}
}
}
Make your own class outside of EntityFrameworkModel.tt - name it Author.cs, make the class partial.
The whole idea of partial is to allow code generators not to care about your code. Of you modify a generated class, the next regeneration kills the changes.
I did same but when I defined the object for Author.cs as:
Ah, no, you did not because then you claim your definition is:
protected override EvoObject ConvertCPV(Author _author)
Which is NOT defining the object.
I can't access the methods defined in GraphData\Author.cs
Because namespace? Check the namespaces - bad to have them in a subfolder when they belong in a the same namespace as EntityFrameworkModel.tt
whereas the properties defined in EntityFrameworkModel.tt\Author.cs are only
accessible.
Partial classes do not allow changes in another partial - not for the moment, a substition syntax is considered.
Let's say we have a base class Rectangle and a derived class Square:
namespace Shapes {
using System.Foo;
public class Rectangle {
public Rectangle(int l, int w){}
}
}
namespace Shapes {
public class Square : Rectangle
public Square(int l, int w){}
}
Does the Square class have to explicitly say that it is using System.Foo? I'm getting erratic results. In one project the using directives seem to be inherited and in a web application they aren't.
using statements, in this context, don't compile to code -- they are helpers to make your code read cleaner for others. As a result, they are not "inherited".
So, to answer your question, your Square class needs to reference System.Foo - either with a using statement, or by using a fully qualified class name.
A using statement will only propagate to the next set of closing braces (}) from the level it was declared on within the same the file.
//From File1.cs
using System.Baz;
namespace Example
{
using System.Foo;
//The using statement for Foo and Baz will be in effect here.
partial class Bar
{
//The using statement for Foo and Baz will be in effect here.
}
}
namespace Example
{
//The using statement for Baz will be in effect here but Foo will not.
partial class Bar
{
//The using statement for Baz will be in effect here but Foo will not.
}
}
//From File2.cs
namespace Example
{
//The using statement for Foo and Baz will NOT be in effect here.
partial class Bar
{
//The using statement for Foo and Baz will NOT be in effect here.
}
}
using directives are only shared if the classes are in the same file and they are not nested in the classes themselves like in your example.
For instance:
using System.Foo;
namespace N
{
class A {}
class B {}
}
If this is all in one file, A and B can both use Foo.
I think everyone is missing the point when it comes to using directives. They really have nothing to do with the class at all. using directives in a code file (.cs, .vb, etc...) are not part of the classes defined within the file. They are used by the compiler to resolve namespaces when compiling.
using System.Foo;
namespace Shapes {...
Importing should always be top most and not within a namespace. This will allow the entire structure of the class to rely on that import when needed.
SO, my concern is not being completely aware if this is the best approach for my situation.
Lets, say I got a base class "Entity". Assuming the purpose is to construct a class hierarchy system.
public class Entity
{
public int _hp;
private int _max_hp;
public Entity(int hp)
{
_max_hp = hp;
_hp = _max_hp;
}
}
And we got other derived classes
public class d_class1: Entity
{
public d_class1(int hp):
base(hp)
{
}
}
public class d_class1_Mono: MonoBehaviour
{
public d_class1 d1;
}
public class d_class2: Entity
{
public d_class2(int hp):
base(hp)
{
}
}
public class d_class2_Mono: MonoBehaviour
{
public d_class2 d2;
}
(Excuse the bad naming conventions, was done on purpose)
Assume the scripts that are inheriting from Mono are attached to different objects in the scene.
I want to be able to distinguish which "class" I currently have when "click" on the unit.
Is there anyway I can avoid having to check between all possible classes I may have.
ex.
obj = gameObject containg the component d_class2_Mono
if(obj contains d_class1)
do something with d1
else if(obj contains d_class2)
do something with d2
else
error("Unknown class derivation");
I feel myself having to do this sometimes to do something like get the hp, just because I need someway of accessing the component. Maybe this is not the best approach. Currently, this is all simple, but each of these class will be in their own way different from the other (i.e. different abilities, etc)
So, hoping someone could shed some knowledge in my understanding.
The GameObject that you attach the MonoBehaviour you can have a handler specifically for that object. For example you could implement "void OnUpdate()" on the d_class1_Mono and a different update function for d_class2_Mono.
If you assume that you don't know which object you have clicked on (because this is being routed through some other class/function) -
You can do:
obj.GetComponent<d_class1_Mono>()
and
obj.GetComponent<d_class2_Mono>()
Whichever one returns a non-null reference has that script attached to it. Hope this makes sense.
I would probably define a virtual or abstract method in the Entity class which each inherited classes would implement. For example, if you have both mobile and immobile entities, and you have a void MoveToPosition(Position pos) method defined in Entity:
// Mobile entity
public class d_class1: Entity
{
// ...stuff...
public void MoveToPosition(Position pos)
{
TweenPosition(_currPosition, pos, movementSpeed);
}
}
// Immobile entity
public class d_class2: Entity
{
// ...stuff...
public void MoveToPosition(Position pos)
{
// Do nothing
}
}
Then within your logic/update loop, you can simply tell ALL entities to MoveToPosition(...) and those that shouldn't respond will simply do nothing.
I find that coding is cleaner when I've got a common interface or class with a common "do something" method, and let each derived class handle the "how" of that method call in its own ways.