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
Related
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
In the C# code listed below, I get a "NullReferenceException" with the error:
"Object reference not set to an instance of an object"
I guess the error is related to the inheritance and/or the template definitions. The list gets initialized, and when debugging I can confirm that the list does not point to NULL. I can't figure out how to do this in another way. (Sorry about the confusing class names / structure). The exception happens here: this.localSMT.doSomething(base.list);
public class VTEST<V>
{
public List<V> list;
public LocalSMT<V> localSMT;
public VTEST()
{
list = new List<V>();
}
}
public class VTEST_FSUB<V> : VTEST<V>
{
public VTEST_FSUB()
{
do_virtual();
}
public void do_virtual()
{
this.localSMT.doSomething(base.list);
}
}
public class VTEST_RUN : VTEST_FSUB<int>
{
public VTEST_RUN()
{
localSMT = new VTEST_SUB();
}
}
public class LocalSMT<V>
{
public LocalSMT() { }
public virtual void doSomething(List<V> value) { }
}
public class VTEST_SUB : LocalSMT<int>
{
public VTEST_SUB(){}
public override void doSomething(List<int> value) {
System.Console.WriteLine("VTEST_SUB VIRTUAL");
}
}
class Program
{
Program() {}
static void Main(string[] args)
{
VTEST_RUN run = new VTEST_RUN();
}
}
The problem is that the VTEST_FSUB<V> constructor body is executing before the VTEST_RUN constructor body. So when do_virtual is called, localSMT is still null. Then do_virtual tries to call a method on localSMT, hence the exception.
Basically the initialization order for any class in the hierarchy is:
Initialize variables which have been declared within an initializer at the point of declaration (any other variables just have the variable type's default value)
Chain up to the base class initialization
Execute the constructor body
See my article on constructor chaining for more details.
Lessons to learn:
Avoid public fields. If you use private fields, it's easy to find every piece of code that reads them and writes to them
Ideally, use readonly fields: if you'd passed the value up the constructor chain and set it in the VTEST<V> constructor, you wouldn't have had a problem. (Admittedly readonly fields can still be a pain because of the next point...)
Avoid virtual method calls in constructors. In this case that wasn't the problem, but you could easily have had the same issue if do_virtual had been abstract in VTEST_FSUB<V> and overridden to call localSMT.doSomething in VTEST_RUN. It would still have executed before the constructor body had run, which would be surprising. Anything you call within a constructor is operating on a partially-initialized object, which is a precarious situation.
Avoid large inheritance hierarchies. They're a pain to work with and reason about.
Follow .NET naming conventions! Your code is partly hard to read because it's so unidiomatic. Even when you're just giving sample code, at least follow the capitalization conventions.
try:
public void do_virtual()
{
localSMT=new LocalSMT<V>();
localSMT.doSomething(list);
}
in public class VTEST_FSUB<V> : VTEST<V>
You are not instatianing localSMT before using, so it's not working.
EDIT: OR
public class VTEST<V>
{
public List<V> list;
public LocalSMT<V> localSMT;
public VTEST()
{
list = new List<V>();
localSMT = new LocalSMT<V>();
}
}
initialize it in constructor, preferable.
Second solution is cleaner.
public class VTEST_RUN : VTEST_FSUB<int>
{
public VTEST_RUN()
{
localSMT = new VTEST_SUB(); // BAD! localSMT isn't initialized yet!
}
}
I believe that you have failed to new up one of your objects:
public void do_virtual()
{
localSMT = new LocalSMT<V>();
localSMT.doSomething(list);
}
Make sure that when you are trying to use an object that you initialize them! And don't worry too much, this is a very common problem in coding.
I'm trying to figure out why this is not working...
public static class ApplicationType
{
private static ApplicationEnum application = ApplicationEnum.App1;
public static ApplicationEnum Application
{
get { return application; }
set { application = value; }
}
public enum ApplicationEnum
{
App1,
App2,
App3
}
}
I want to access Application from another class, such as...
public partial class MainWindow : Window
{
ApplicationType. //<-- Intellisense shows only ApplicationEnum }
Thanks.
EDIT: Problem was that I was not trying inside the MainWindow as in this example as I thought I was.
You're in the middle of a class declaration. You need to declare a field, method etc. For example, this should be fine (if you make ApplicationEnum public):
private ApplicationEnum foo = ApplicatoinType.Application;
Until you've made ApplicationEnum public, you'll find that your Application property will fail to compile - you can't declare a public property of a type which isn't itself public.
I have created an engine that takes in 3rd party plugins (DLL's) that implement an interface.
Since I have no control over the code that gets plugged in, I want to be able to run 1 specific method (from the interface) from the correct class (GetTypes loop untill I find the interfaced class ).
Since anyone can create nice constructor code that executes on Activator.CreateInstance, I can solve that by using FormatterServices.GetUninitializedObject. But that does not help when code is being initialized on fields in the class.
public class myclass : myinterface {
public someotherclass name = new someotherclass()
public myclass() {
//Unknown code
}
//I only want this run.
public string MyProperty{
get {
return "ANiceConstString";
}
}
}
The problem with both ways (CreateInstance/GetUninitializedObject) is that the constructor of someotherclass will be run.
Before you start analyze my needs. This is only run in the initializing of the engine to get a set of standard values. If this get'er relies on other initialized values the "plugin" will be marked as failed as there is no valid value returned. If not marked as failed, later on the class will be loaded properly with Activator.CreateInstance().
So stick to this question:
Does .Net support any way to create an 100% non-initialized class?
Update for the answers. I tested this before I posted my question.
For the answer that someotherclass wont run, I allready tested that and it is run if static.
public class myclass : myinterface {
static Tutle test;
public myclass () {
test = new Tutle();
}
public class Tutle {
public Tutle() {
MessageBox.Show("RUN!");
}
}
}
CreateInstance shows the messagebox. GetUninitializedObject does not.
public class myclass : myinterface {
static Tutle test = new Tutle();
public myclass () {
}
public class Tutle {
public Tutle() {
MessageBox.Show("RUN!");
}
}
}
CreateInstance shows the messagebox. GetUninitializedObject shows the messagebox.
Is there a way to get around static field intializers and ctors?
Simply:
var obj = (myclass)FormatterServices.GetUninitializedObject(typeof(myclass));
That will not run the constructor / field initializers. At all. It will not run the constructor for someotherclass; name will be null.
It will, however, execute any static constructor that exists, if necessary under standard .NET rules.
HOWEVER! I should note that this method is not intended for ad-hoc usage; its primary intent is for use in serializers and remoting engines. There is a very good chance that the types will not work correctly if created in this way, if you have not subsequently taken steps to put them back into a valid state (which any serializer / remoting engine would be sure to do).
As an alternative design consideration:
[SomeFeature("ANiceConstString")]
public class myclass : myinterface {
public someotherclass name = new someotherclass()
public myclass() {
//Unknown code
}
}
Now you can access the feature without instantiation; just use:
var attrib = (SomeFeatureAttribute)Attribute.GetCustomAttribute(
type, typeof(SomeFeatureAttribute));
string whatever = attrib == null ? null : attrib.Name;
with:
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
public sealed class SomeFeatureAttribute : Attribute
{
private readonly string name;
public string Name { get { return name; } }
public SomeFeatureAttribute(string name) { this.name = name; }
}
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);
}
}