class not behaving as internal by default - c#

When I define a class inside my c# windows application project, the class is supposed to be internally available to the project.
So I should be able to declare that type of class from within my form, without defining my class as a public class.
But I am getting an accessibility error, which goes away when my class is redefined as public, instead of the default (which is supposed to be internal to the assembly).
This is not a repeat question. This question differs from other accessibility issues I have seen.
All items in my project (forms, classes, etc.) should belong to the same assembly, so what's going on?
Is default scope of class internal or not? Research says its supposed to be internal, so this code is supposed to work....
I get...
"Inconsistent accessibility. Field type Queue is less accessible than Form1.Queue"
See code below.
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Queue Queue; // <-- PROBLEM LINE
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
here is the definition of queue; i don't think its really important, but it was requested by a commenter; when I make the class Public, all problem is solved. But that doesn't make sense if the default scope is supposed to be internal, it should not force me to make public:
namespace WindowsFormsApplication3
{
class Queue
{
private const int DEFAULTQUEUESIZE = 100;
private int[] data;
private int head = 0, tail = 0;
private int numElements = 0;
public Queue()
{
this.data = new int[DEFAULTQUEUESIZE];
}
public void Enqueue(int item)
{
if (this.numElements == this.data.Length)
{
throw new Exception("Queue full");
}
this.data[this.head] = item;
this.head++;
this.head = this.head % this.data.Length;
this.numElements++;
}
public int Dequeue()
{
if (this.numElements == 0)
{
throw new Exception("Queue Empty");
}
int queueItem = this.data[this.tail];
this.tail++;
this.tail = this.tail % this.data.Length;
this.numElements--;
return queueItem;
}
}
}

So by adding some guesswork to your question, if the type in question is
internal class Queue
then, quite obviously,
public Queue queue;
is an error - you have a public field of an internal type. How would you expect that to work? The problem is not that your Form has no access to Queue. It's that something from outside your project has access to the Form, has access to the public field, but it does not have access to the type of that field. That makes no sense, how do you expect an external class to make sense of a field whose type it cannot access?
If you declare the Queue as public - the problem goes away, the type is now externally visible.
If you declare the field as internal (or even private) - the error also goes away, as anything accessing that field also has access to the type.
I hope this explains the issue. On a side-note: declaring public fields is usually a mistake, if you want it to be accessible from the outside, use a property:
public Queue Queue {get; set;}

Your Form is declared public and contains a public field of your Queue class. Since Queue isn't public, the compiler refuses to compile your code. If you want Queue to be internal, declare the field as internal or private

Related

How can I access a list that is created in a static object that is part of another class?

What I would like to do is to have a list that is in an object counts that is defined in the App class as a static when my application starts:
Here's the object:
public class Counts
{
public Counts()
{
public static List<CntQty> CardClicks2m;
}
}
In my application I declare this
am using the following code:
public partial class App : Application
{
public static Counts counts = new Counts();
public App()
{
}
}
Now I try to use load some data into the list but it gives me the error below. Note that this function is in another class.
public void GetClickHistory()
{
App.counts.CardClicks2m = db2.Query<CntQty>(sql);
The last line of the code is giving me an error saying
counts.CardClicks2m cannot be accessed with an instance reference;
qualify it with a type name instead.
I have tried a few different ways to make this work. One by removing the static and creating the object in the app constructor. This also didn't seem to work so I am hoping someone can point me in the right direction or at least suggest something.
i guess scope of variable is not right , you need to do like this
public class Counts
{
public static List<CntQty> CardClicks2m;
public Counts()
{
}
}
The error is pretty self explanatory, you cannot access a static property using an instance variable. all you need to do is use the typename. So this:
App.Counts.CardClicks2m
Becomes this:
Counts.CardClicks2m
You may need to specify the full namespace of the Counts class:
Some.Namespace.Counts.CardClicks2m
The error you are receiving is because you are trying to access to a static member from a instance object
public void GetClickHistory()
{
App.counts.CardClicks2m = db2.Query<CntQty>(sql);
EDITED after comments:
Try this (accessing the static member from the class):
public void GetClickHistory()
{
Counts.CardClicks2m = db2.Query<CntQty>(sql);
As CardClicks2m is declared static, it must be accessed from the class scope. If Counts class doen't have any other code, you can declare
public static class Counts
And there is not neccesary to create an instance of counts
public static Counts counts = new Counts(); //this is not neccesary
As your CardClicks2m-member is static there´s no need to have any instance of your Counts- or aven your App-class. The member exists once per appdomain however. Having said this in order to access CardClicks2m you don´t have to create an instance of your Counts-class within App.
Use this instead:
class MyClass
{
void DoSometjing()
{
Counts.CardClicks2m = db2.Query<CntQty>(sql).ToList();
}
}
Be aware to that Query will surely not return a List<CntQty>, but an IQueryable<CntQty>, that´s why you should call ToList afterwards.
Furthermore you can´t declare a member within a method or constructor. Thus declare it within the class´-body instead of the constructor:
public class Counts
{
public static List<CntQty> CardClicks2m;
public Counts() { /* any further initialzation */ } }
}

Incompatibility accessibility error, what is that means?

I have a class Computer.cs, which belongs to the form Computer, and I have an independent class Indicators.
In my code I'm getting an error:
Incompatibility accessibility: accessibility return type "WF.Code.Indicators"
method is below than accessibility return type "WF.Computer.ShowForm ()"
What is that means?
Computer.cs
namespace WF
{
public partial class Computer : Form
{
Code.Indicators indicators = new Code.Indicators();
public Computer()
{
if (indicators.isComputerAlreadyRunning == false)
{
InitializeComponent();
indicators.isComputerAlreadyRunning = true;
}
}
public Code.Indicators ShowForm() // Error
{
return new Code.Indicators(indicators.isComputerAlreadyRunning);
}
}
}
Indicators.cs
namespace WF.Code
{
class Indicators
{
public Indicators(bool isComputerAlreadyRunning)
{
this.isComputerAlreadyRunning = isComputerAlreadyRunning;
}
public bool isComputerAlreadyRunning = false;
}
}
Your method:
public Code.Indicators ShowForm() // Error
{
return new Code.Indicators(indicators.isComputerAlreadyRunning);
}
It returns an Indicators object and is of public visibility. However the type Indicators itself is not public, it's internal (by default, since you did not specify it ; see this answer for more information).
Declare the class Indicators as public to solve the issue, or set the method ShowForm as internal.
Edit:
To better explain why the compiler complains, imagine your code is actually compiled to a library. Somebody includes this library from another assembly to use it, and this somebody is going to call this public method ShowForm(because he can!).
He is going to get a reference pointing to an Indicators but from his point of view (actually from his assembly's point of view), he does not know what the class Indicators is, because its visibility is internal (as I said, by default). internal elements are not exposed to other assemblies on the contrary of public elements. This creates an incoherence and that it the reason why the compiler complains.
It means that since ShowForm is public the return type must also be public.
you Indicators class is now :
namespace WF.Code
{
class Indicators
{
public Indicators(bool isComputerAlreadyRunning)
{
this.isComputerAlreadyRunning = isComputerAlreadyRunning;
}
public bool isComputerAlreadyRunning = false;
}
}
but should be :
namespace WF.Code
{
public class Indicators
{
public Indicators(bool isComputerAlreadyRunning)
{
this.isComputerAlreadyRunning = isComputerAlreadyRunning;
}
public bool isComputerAlreadyRunning = false;
}
}
in .NET if you instantiate a class outside the class' area then either should be internal or public code access.. otherwise such like you created class as private ( if there is no code access implementation as your implementation of Indicators - class Indicators- compiler accept that as private and you can't access out of the class)
Even if it was internal code access and you refer it as public you will get the same exception..
when your class' code access is public then should be all instances / inside methods or calls should be public, if it is internal then can be internal or private or protected

Getting forces that are acting on a Body

Since I am building a physics teaching platform, I need to know the total force that is acting on an object at the moment. This way, I may draw arrows showing this resultant force for students to understand what is going on.
I dug into the source of Farseer and found the internal Vector2 variable Force. Since it is internal, I cannot access it from my teaching platform since they are in different assemblies.
Will anything bad happen if I change the modifier to, let's say private, and add a getter function to it?
OR
Is there a better way to get the resultant force currently acting on an object?
Since it seems you have access to the source, the easiest approach to expose that variable is to add a public getter to the class in which it resides. An instance of that class will have access to the internal variable.
EDIT: (Added code examples)
It is all about where the code accessing the internal value exists. Hopefully the example below will illustrate this for you. Assume that you have a solution with two projects, one called ExternalAssembly, the other MyApplication. MyApplication has a reference to ExternalAssembly to access its classes.
Project: ExternalAssembly
namespace ExternalAssembly
{
public class MyClass
{
internal string hiddenString;
public MyClass()
{
this.hiddenString = "This is my value.";
}
public string Exposed
{
get { return this.hiddenString; }
}
}
public class MyClass2
{
private MyClass classInstance;
public MyClass2()
{
this.classInstance = new MyClass();
}
public string Exposed2
{
get { return this.classInstance.hiddenString; }
}
}
}
Project: MyApplication
namespace MyApplication
{
using ExternalAssembly;
public class CallInternalTest()
{
MyClass classInstance = new MyClass();
MyClass2 class2Instance = new MyClass2();
// this will fail since hiddenString is an internal variable
Console.WriteLine(classInstance.hiddenString);
// this will succeed since Exposed is a public member
Console.WriteLine(classInstance.Exposed);
// this will also succeed since Exposed2 is a public member
Console.WriteLine(class2Instance.Exposed2);
}
}

Binding objects to WinForms controls and access modifiers

I'm having some trouble understanding access modifiers; I want to know better when to use what level of access, especially for properties--just links to good tutorials on that subject could be its own question.
But more specifically, I don't understand why an object bound to a WinForm control has to be public. So I create my object:
public class Foos : List<Foo>
{
}
public class Foo
{
private int bar;
public int Bar
{
get { return bar; }
set { bar = value; }
}
}
then bind it to a DataGridView
public partial class Form1 : Form
{
private Foos formFoos;
public Form1()
{
InitializeComponent();
formFoos = new Foos();
AddFoo();
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = formFoos;
}
/// <summary>
/// generate some test values
/// </summary>
private void AddFoo()
{
for (int i = 1; i <= 5; i++)
{
Foo foo = new Foo();
foo.Bar = 5 * i;
formFoos.Add(foo);
}
}
}
Works fine. But what if I don't want to expose Foo.Bar outside my assembly? If I make it internal int Bar I get an empty dataGridView1. If I make it protected I get a compiler error, because of course Form1 is not derived from Foo.
How does a control in a form in my program not match the definition of internal though?
Internal members are accessible only within files in the same
assembly.
General wisdom on how you make these declarations in a systematic way also welcomed.
You should mark the whole Foo class as internal.
This way, the entire Foo class and all it's members will be invisible outside the assembly.
Form1.dataGridView1 needs Foo.Bar to be public, otherwise it won't be able to make use of it.
Now, because Foo is already marked internal, it can expose Bar as public with no risk of exposing it outside the assembly.
This should make both Form1.dataGridView1 and you equally happy.
Please note that by marking Foo as internal, Foos should also change from public to internal because Foos may not have a higher access level than the class it's derived from.

can we access a private variable using an object

We cannot access a private variable of a class from an object, which is created outside the class, but it is possible to access when the same object is created inside the class, itself. why??
class Program
{
private int i;
public void method1()
{
Program p = new Program();
p.i = 5; // OK when accessed within the class
}
}
class AnotherClass
{
void method2()
{
Program p = new Program();
p.i = 5; //error because private variables cannot be accessed with an object which is created out side the class
}
}
Now I think every one got my point??
In both the cases above, we are accessing the private variable 'i' through the object 'p'. But inside class it is allowed, outside the class not allowed. Can anybody tell me the reason behind this??
You can access i from within the class because private members can only be accessed by members of the class. In this case it looks strange because p is a different object than the object that accesses the variable, but its still the same class and the restriction is on the class level not on the object level.
class Program
{
private int i;
public void method1()
{
Program p = new Program();
p.i = 5; // OK when accessed within the class
}
}
You can not access i from within another class (unless it is an inner class but that's a different story). Which is completely as expected.
class AnotherClass
{
void method2()
{
Program p = new Program();
p.i = 5; //error because private variables cannot be accessed with an object which is created out side the class
}
}
I understand the point you want to make. The restriction on class level looks counter intuitively. And maybe this is wrong. But the member variables are still only accessible from within the class, so you still have total control to guarantee the encapsulation of your privates.
why??
It's true by the language specification. The access modifier private has the semantics that only the class or struct declaring a member is allowed to access that member.
I suggest reading the specification for details. In particular, check out
§3.5.1 Declared Accessibility
§3.5.4 Accessibility constraints
§10.2.3 Access Modifiers
§10.2.6.2 Declared Accessibility
§10.2.6.5 Access to private and protected members of the containing type
In both the cases above, we are accessing the private variable 'i' through the object 'p'. But inside class it is allowed, outside the class not allowed. Can anybody tell me the reason behind this??
Because access modifiers don't pertain to the object, they pertain to the class (or assembly, for the internal modifier).
Even if you access it from a different object, or a static context, as long as you stay in the same class, accessing a private member will work. It's private to the class, not its instances.
You are maybe confusing object and class, public/private/protected/internal affect class visibility not object visibility. That means an object of a class can access attributes of another object of the same class, even if they are private.
I am not sure I understood your question correctly...
if accessing outside the class is the option required then try properties.
This belongs to OOP. The answer would be because its private, otherwise if all private variables would be accessable from outside the class the object's concept wouldnt make any sense.
You Can Access the private variables in the following process also...
namespace OOPSProj
{
class Program
{
private int i;
public void Methode1()
{
Program objprog2 = new Program();
objprog2.i = 15;
Console.WriteLine("i= " + objprog2.i);
}
static void Main(string[] args)
{
Program objprog = new Program();
objprog.i = 10;
Console.WriteLine("i= " + objprog.i);
objprog.Methode1();
}
}
class Test
{
static void Main()
{
Program objproj3 = new Program();
objproj3.Methode1();
}
}
}

Categories

Resources