I really dont understand why, but it seems like the internal access modifier doesn't work :S
I've looked at this tutorial:
http://msdn.microsoft.com/en-us/library/7c5ka91b(v=vs.110).aspx
But for me, it compiles.
ALso, i have a bought a book Illustrated C# 2012. And the author explains the internal class etc etc... But still, it doesn't do anything.
Here is my complete code that works EVEN with internal access.
//Program.cs
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Class1 myclass = new Class1(); //works
myclass.display(); //works
myclass.display2(); //works even though its not public :S
Console.Read();
}
}
}
-
//Class1.cs
namespace ConsoleApplication1
{
internal class Class1
{
public void display()
{
Console.WriteLine("display()");
}
internal void display2()
{
Console.WriteLine("display2()");
}
}
}
I can even access the function internal void display2() :S
internal means "Acessible by anything in the same assembly".
Because your class Class1 and class Program are in the same assembly, class Program can access display2().
I think you've accidentally put them in the same assembly; if you look carefully at Microsoft's sample code you'll see it says "Assembly1.cs" and "Assembly2.cs"
If you are using Visual Studio, the easiest way to test this with a different assembly is to create a new class library project in the same solution. That will then count as a separate assembly. You'd have to add to the main project a reference to the new project (via Add Reference and then the Solution tab).
There's a Stack Overflow question about "What's an assembly?" if you need more info.
If both classes are in the same assembly then internal is working as expected.
The internal modifier is used to make sure that types and members are only available to files in the same assembly.
Ref: http://msdn.microsoft.com/en-gb/library/7c5ka91b%28v=vs.80%29.aspx
From MSDN;
Internal types or members are accessible only within files in the same
assembly
Since Program and Class1 in the same assembly, there shouldn't be a problem..
What does the internal modifier do exactly? It states that "The
intuitive meaning of internal is 'access limited to this program.'"
In other words, no external program will be able to access the
internal type.
The internal access modifier means the member can be accessed anywhere from within the same assembly.
In your case, the classes "Program" and "Class1" are within the same assembly, therefore, Program can access display2 (Which is also internal and within the same assembly).
If you don't want display2 to be accessed from the Program class, you could simply make it private and therefore it would only be accessible from Class1.
Related
After attempting to research C# namespaces further (coming from a c++ background) I think I understand the purpose of namespaces in general - to organise classes for the user, and to avoid conflicts. This practise, I imagine, still holds just as true for programs as it does for libraries.
What I don't understand is why exactly classes housing the Main() function would need to be part of a namespace.
I can't imagine that the main function would need to be called elsewhere for any reason, so organisation and conflict prevention ought not to be the reason.
Is it simply to show other developers what namespace to use throughout the rest of the program's classes? Or is there some deeper reason for it that is going over my head?
What I don't understand is why exactly classes housing the Main() function would need to be part of a namespace.
For sake of simplicity, we're going to assume that the class that contains Main() is called Program.
The Program class does not need to be in a namespace. For example, explicitly declaring the class:
// Program.cs
public class Program {
public static void Main(string[] args) {
System.Console.WriteLine("hi");
}
}
namespace MyNamespace {
public class Data {
public int Val {get;set;}
}
}
or using Top Level Statements
// Program.cs
System.Console.WriteLine("hi");
namespace MyNamespace {
public class Data {
public int Val {get;set;}
}
}
SharpLab (the links above) shows you what the compiler will output, and in both the Program class doesn't exist inside a namespace, even though other classes will.
And for the record, this is not limited to the Program class. You can put any/all of your types in the "global" namespace. You just lose the "categorization" benefit of namespaces.
I can't imagine that the main function would need to be called elsewhere for any reason
I'd agree. Normally you'd let the .Net runtime call your Main method. I'm sure you can think of some reason to do so, but really that's up to the architecture of your application. One maybe valid use case would be automated testing with a testing framework (xUnit, MSTest, etc) in a sibling assembly.
Now, say you did want to call the Main method yourself, as long as the Fully Qualified Type doesn't conflict with something else, you can still call it just like normal.
public class Program
{
public static void DoThing() { }
}
namespace MyNamespace
{
public class Data
{
public void ActivateDoThing() => Program.DoThing();
// or, if you run into a conflict
public void ActivateDoThing() => global::Program.DoThing();
}
}
Is there a reason for giving the class holding Main() a namespace in C#?
This is due to the editor you're using. Except for the Top Level Statements feature, when you create a new project with the "Console Application" template, it will have the Program class wrapped in a namespace, which is consistent with creating a new code file for a new class. This is just a decision the authors of the template have chosen, but at least it does follow the rule that every file has a namespace block. Familiarity can enhance readability, even if its inefficient.
That's really the point of the Top Level Statements feature - get rid of all the boilerplate. Technically, you don't need a namespace for the entry point class - so get rid of it. Most of the time, you don't add anything to Program besides the Main method, so don't require the user typing the class or method signatures. Just let the user get to the Main logic as fast as possible and the compiler can generate the rest.
That's really about it. Why is the namespace there? Mostly for consistency. Does it need to be there? Nope, not at all.
When you create a WinForm App, you get an automatically generated template of Program class in the Program.cs file.
Which looks something like this:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
My question is, why is the Program class declared as static?
If I remove the static declaration it still works fine.
The reason for the question is that I thought it could be nice to have Program inherit from a base class that would implement handling of Application.ThreadException and AppDomain.CurrentDomain.UnhandledException instead of implementing it more or less the same for all of my projects.
It just follows a design guideline, that classes that contain only static methods should be marked as static. More information can be found here.
There is no problem in making your Program class not static, the only thing that is required is the static Main method as an entry point, as you've already noticed. You can add instance methods to the Program class, instantiate it and use as any other class. However this is not a clear way, as this violates the Single Responsibility Principle. Program's responsibility is to provide an entry point for the application, so it shouldn't do anything more. For this task it needs only one static method called Main. And as it contains only static methods, it should be marked as static to conform to C# coding guidelines.
In general, it is convenient to know that a class is static, so you know at first glance that it contains only static methods. It is a very readable way of expressing how a class should be used. In this example it isn't very essential, as no one uses Program explicitly, however for the sake of strictness it should be static.
My question is, why is the Program class declared as static?
As you note, it doesn't have to be. In fact, in my version of Visual Studio (Visual Studio 2015 Enterprise Update 1) the default program for "Console Application" is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
}
}
}
But wait, why is Main static again?
This answer does an excellent job of explaining why Main must be static. In short, the answer states that Main must be static because the alternative is that the CLR would have to call the constructor on Program in order to call Program.Main. But think about it, nothing happens before the entry point so no such constructor can be called!
The reason for the question is that I thought it could be nice to have Programinherit from a base class that would implement handling of Application.ThreadException and AppDomain.CurrentDomain.UnhandledException instead of implementing it more or less the same for all of my projects.
This is a really good idea; DRY is one of my favorite programming principles. However, to do it in the way you were thinking, Program would need to derive from a base object of type, say, ProgramBase and call some sort of protected method. Something like this perhaps?
internal class Program : ProgramBase
{
static void Main(string[] args)
{
// ERROR: "an object reference is required for the non-static
// field, method, or property ProgramBase.MainWrapper();"
MainWrapper();
}
protected override void DoMain()
{
// do something
}
}
internal abstract class ProgramBase
{
protected void MainWrapper()
{
try
{
// do some stuff
DoMain();
}
catch(...)
{
// handle some errors
}
}
protected abstract void DoMain();
}
The problem arises that to solve the problem with inheritance, Program.Main() must call some sort of non-static method.
OK, now lets solve the problem a different way. Let's create an ApplicationBase abstract class for applications of different types to derive from.
class Program
{
static void Main(string[] args)
{
var myApp = new MyApplication();
myApp.RunApp();
}
}
public class MyApplication : ApplicationBase
{
protected override void DoRunApp()
{
// do my stuff
}
}
public abstract class ApplicationBase
{
public void RunApp()
{
try
{
// create AppDomain, or some other construction stuff
// do some stuff
DoRunApp();
}
catch(...)
{
// handle some errors
}
catch(...)
{
// handle some other errors
}
}
protected abstract void DoRunApp();
}
NOW we're getting somewhere. Depending on what you are creating in your setup/creation phase, your DoRunApp() signature may change but this sort of template should accomplish what you're looking for.
Thanks for reading.
Avoid over-thinking this. This code just comes out of the project template, pre-cooked in C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ProjectTemplates\CSharp\Windows\1033\WindowsApplication\Program.cs
There's nothing to stop you from modifying that code, removing the static keyword is entirely reasonable if that's the way you prefer it. There is a bit of logic to it, you after all have only one program so declaring it static does make sense. But compare it to the project template for a Console mode app, It also declares a Program class but didn't make it static. It doesn't make extra sense at all to make that class not static for a console app.
There are certainly other good reasons to modify the project template code. It for example puts the Dispose() method for a Form derived class in the Designer.cs file. Not a great place for it, the "never modify designer generated code" rule does get Winforms programmers paralyzed. Moving that method into the Form.cs file and then modifying it is just fine.
This is merely "most likely to fall in the pit of success" code. Never hesitate to change it.
The reason for it to be static is, because it only has static methods and nothing else.
If you would now add interfaces, base classes and non static methods/properties/members you would have to create an instance of that class to use them (which is forbidden because of the static class). Which is still fine, and could even be done in the static Main method, but it could be misleading or is not the intended purpose of that class. I would create a MyApplication class anway, instance it in the static Main and create my Form from there.
Regarding your Exception handlers. You can still create a manager class that does that for you, which you just call from your Main and can be reused in all your programs.
There is only one instance of the main method in memory
and there is one entry point for each C# application.
I recently branched out into C# written with Visual Studio Express from C++ written with gVIM. I've been told I'll have to unlearn a lot of stuff to really use C# effectively, but here's my question:
In C++ when writing a class or data type, I would have separate files for the class definition and the driver program. I would then #include the class in the driver program in order to use it. It isn't terribly clear how to do this in Visual Studio Express 2013 and all the tutorials I've looked up have the class definition and the Main() routine in the same file.
I currently have only two files in my solution folder: the driver program p1.cs and the type definition/implementation targetInt.cs. What is the best way to allow p1.cs to work with my targetInt.cs type? Will it simply have access by virtue of being part of the same solution? If so, how to I get around not having a Main() routine in my type definition?
Here is a screenshot of the solution and the error I'm getting when I try to build the solution. I don't get an error for trying to declare a targetInt object in p1.cs which points to the namespace already being shared.
http://i793.photobucket.com/albums/yy218/tombombodil/solution_zps6a743e2d.png
Let me know if I need to clarify anything.
It's really not terribly complicated, but it is different from C++. So if you have one file that looks something like this:
namespace MyNamespace
{
public class MyClass
{
//...stuff
}
}
And then you want another file with your Main (which you will for anything more than a trivially simple project), it would look something like this:
using MyNamespace; // unless you use the same namespace for both
namespace SomeOtherNamespace
{
class Program
{
static void Main(string[] args)
{
var c = new MyClass();
// alternatively, without the using statement, you can just fully qualify
// your class name like so:
// var c = new MyNamespace.MyClass();
}
}
}
But do note that the files need to be in the same project. If they are in different projects you can still do it, but you have to add a reference to the project with MyClass to the project with Program. What you can't do is just have an orphaned C# file floating around in your solution and expect it to work.
The problem as you've written boils down to the simple lack of shared namespaces - because targetInit exists in a separate namespace, Program needs a using targetInit.cs to access the targetInit type. They can, however, access each other by virtue of being in the same project - a Solution can contain multiple Projects, and if they don't reference each other, they can't access each other's types.
Usually, the naemspace of any given class is actually the folder path to it, and the class name is the same as the file name (which Visual Studio does for you when you make new class files).
As for the Main() definition, you only want one of these since you only have a single entry point for the system to jump to when your program begins - having multiple Main() functions doesn't make much sense when the OS needs a clear place to begin execution.
The Main() method and class definitions sitting in the same file is a convenience so all the code can be read together - to get an idea for how actual projects are set up, trying going to GitHub and forking a couple of open-source projects.
there are two approaches to use another class in C# directly:
1-putting that class in the same namespace of my class(even if they were in separate files), this code clarify this:
//file TargetInt.cs
namespace MyNameSpace
{
class TargetInt
{
}
}
//file p1.cs
namespace MyNameSpace
{
class p1
{
static void Main(string[] args)
{
}
}
}
notice that both classes are in MyNameSpace namespace.
2-if the other class is contained within another namespace, you can simply use it by declaring this statement in the upper beginning of the file:
//file TargetInt.cs
namespace OtherNameSpace
{
class TargetInt
{
}
}
//file p1.cs
using OtherNameSpace;
namespace MyNameSpace
{
class p1
{
static void Main(string[] args)
{
}
}
}
with using OtherNameSpace; you can use TargetInt class directly.
I'm noticing the compiler error The type '...' has no constructors defined generated when I erroneously attempt to instantiate a particlar class.
It lead me to wonder how I would go about writing my own class that would precipitate this message when someone attempted to instantiate it.
So the code below, what do I need to do to MyClass?
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
}
}
class MyClass
{
MyClass()
{
}
}
}
This error (CS0143) occurs if the class only defines an internal constructor and you try to instantiate it from another assembly.
public class MyClass
{
internal MyClass()
{
}
}
Also this error could be cause if you are compiling with Framework 4 or higher and embedding the Interop Types into your managed assembly. To get rid of this error you need to turn off (No embed) the Embedded Interop Types.
Instructions to turn off embedding:
On VS2010 Solution Explorer, right click on the Interop Reference that you are using.
Select Properties and look for Embed Interop Types
Change it from True to False
You can read about Embedded Interop Types here.
Pablo
I've managed to reproduce this by:
Creating a static class in a DLL
Using ildasm to decompile it to IL
Editing the IL to remove the "abstract" and "sealed" modifiers from the class
Rebuilding the DLL with ilasm
Compiling a program which tries to create an instance of the class
If you don't remove the abstract/sealed modifiers, the C# compiler recognizes it as a static class and gives a different error message. Of course, you could start off with a "normal" type and just remove the constructors, too.
EDIT: I actually thought I hadn't submitted this, as I saw the "internal" constructor one first. However, I'll leave it now as my version makes the C# compiler correct - there's a difference between a type having no accessible constructors and genuinely having no constructors :)
I believe you would need to make the constructor of the class internal in order to have it throw this exception. I believe you'll also need the class to exist in another assembly.
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
}
}
}
namespace DifferentNamespace
{
class MyClass
{
internal MyClass()
{
}
}
}
As has been said, you can get CS0143 by trying to instantiate a class with an internal constructor from outside its assembly.
But I believe it's a compiler bug. The error generated should be CS0122:
'member' is inaccessible due to its protection level
... which is the error you get if you try to instantiate a class with only a private constructor.
CS0143 used to happen (up to C# 3.0) if you tried to call a constructor for a built-in type like Double, but in C# 4.0 that now generates CS1729:
'type' does not contain a constructor that takes 'number' arguments.
if you pass an argument
Double d = new Double(1.25);
... or no error at all if you don't pass any arguments to the constructor.
Yet another option: the code might be right, but you might work on different projects in different instances of Visual Studio, and therefore you need to build the referenced project first.
I'm noticing the compiler error The type '...' has no constructors defined generated when I erroneously attempt to instantiate a particlar class.
It lead me to wonder how I would go about writing my own class that would precipitate this message when someone attempted to instantiate it.
So the code below, what do I need to do to MyClass?
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
}
}
class MyClass
{
MyClass()
{
}
}
}
This error (CS0143) occurs if the class only defines an internal constructor and you try to instantiate it from another assembly.
public class MyClass
{
internal MyClass()
{
}
}
Also this error could be cause if you are compiling with Framework 4 or higher and embedding the Interop Types into your managed assembly. To get rid of this error you need to turn off (No embed) the Embedded Interop Types.
Instructions to turn off embedding:
On VS2010 Solution Explorer, right click on the Interop Reference that you are using.
Select Properties and look for Embed Interop Types
Change it from True to False
You can read about Embedded Interop Types here.
Pablo
I've managed to reproduce this by:
Creating a static class in a DLL
Using ildasm to decompile it to IL
Editing the IL to remove the "abstract" and "sealed" modifiers from the class
Rebuilding the DLL with ilasm
Compiling a program which tries to create an instance of the class
If you don't remove the abstract/sealed modifiers, the C# compiler recognizes it as a static class and gives a different error message. Of course, you could start off with a "normal" type and just remove the constructors, too.
EDIT: I actually thought I hadn't submitted this, as I saw the "internal" constructor one first. However, I'll leave it now as my version makes the C# compiler correct - there's a difference between a type having no accessible constructors and genuinely having no constructors :)
I believe you would need to make the constructor of the class internal in order to have it throw this exception. I believe you'll also need the class to exist in another assembly.
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
}
}
}
namespace DifferentNamespace
{
class MyClass
{
internal MyClass()
{
}
}
}
As has been said, you can get CS0143 by trying to instantiate a class with an internal constructor from outside its assembly.
But I believe it's a compiler bug. The error generated should be CS0122:
'member' is inaccessible due to its protection level
... which is the error you get if you try to instantiate a class with only a private constructor.
CS0143 used to happen (up to C# 3.0) if you tried to call a constructor for a built-in type like Double, but in C# 4.0 that now generates CS1729:
'type' does not contain a constructor that takes 'number' arguments.
if you pass an argument
Double d = new Double(1.25);
... or no error at all if you don't pass any arguments to the constructor.
Yet another option: the code might be right, but you might work on different projects in different instances of Visual Studio, and therefore you need to build the referenced project first.