This question already has answers here:
Overloading getter and setter causes a stack overflow in C# [duplicate]
(4 answers)
Closed 3 years ago.
This is my code. I am not able to figure out why this code is giving 'Process is Terminated due to StackOverFlowException'.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SadiSDAL4
{
class Program
{
static void Main(string[] args)
{
PrivateVehical privateV = new PrivateVehical("001");
PrivateVehical pVehical = (PrivateVehical)privateV.Clone();
Console.WriteLine("Cloned : {0}", privateV.name);
Console.WriteLine("Cloned : {0}", pVehical.name);
privateV.name = "Sadia's Car";
Console.WriteLine("Cloned : {0}", privateV.name);
Console.WriteLine("Cloned : {0}", pVehical.name);
pVehical.name = "Waheed's Car";
Console.WriteLine("Cloned : {0}", privateV.name);
Console.WriteLine("Cloned : {0}", pVehical.name);
Console.WriteLine(privateV.GetHashCode().ToString());
Console.WriteLine(pVehical.GetHashCode().ToString());
PublicVehical publicV = new PublicVehical("002");
Console.WriteLine(publicV.id);
PublicVehical pubVehi = (PublicVehical)publicV.Clone();
Console.WriteLine("Cloned : {0}", pubVehi.id);
}
}
abstract class Vehical
{
private string vehicalId = "01";
public string name = "Car_1";
public Vehical(string id)
{
this.vehicalId = id;
}
public string id
{
get { return id; }
set { this.vehicalId = id; }
}
public abstract Vehical Clone();
}
class PrivateVehical : Vehical
{
public PrivateVehical(string id)
: base(id)
{
}
public override Vehical Clone()
{
return (Vehical)this.MemberwiseClone();
}
}
class PublicVehical : Vehical
{
public PublicVehical(string id)
: base(id)
{
}
public override Vehical Clone()
{
return (Vehical)this.MemberwiseClone();
}
}
}
This is the output.
Can someone explain what is the cause of it ? Why it is working in first part & not in the other ?
Take a look at this code:
public string id
{
get { return id; }
set { this.vehicalId = id; }
}
Specifically get { return id; }. You are returning property to itself, causing SO error.
Is this what you intended:
public string id
{
get { return this.vehicalId; }
set { this.vehicalId = value; }
}
Your error is occurring on this line of code
Console.WriteLine(publicV.id);
When you try to get the value of a property from your publicV variable it is calling the getter on the base class.
In your case that's this block in the Vehicle class
public string id
{
get { return id; }
set { this.vehicalId = id; }
}
However, when the get is called it executes return id;. So it once again calls the getter for the id property, which executes the return id; line of code again.
So effectively that line of code is calling itself over and over with no resolution, creating your Stack Overflow issue.
(If you're not familiar with this concept see Recursion)
Take a look at the Vehicle's id property again.
You have the right idea for the set version, you assign the value to the vehicleId property. That is also where you should be getting it from.
I expect that if you change the getter to
get { return this.vehicleId; }
that would resolve your issue.
Debugging the code shows you have a cut and paste error.
public string id
{
// having this set to id causes endless recursion
//get { return id; }
//use this instead
get { return vehicalId; }
set { this.vehicalId = id; }
}
Your error is caused by this definition below:
public string id
{
get { return id; }
set { this.vehicalId = id; }
}
That is because the get call is returning a call to itself, that is, get Id calls get Id, which calls get Id, over and over until you run out of memory and get a StackOverflowException. I guess you meant to do this:
public string id
{
get { return vehicalId; }
set { this.vehicalId = id; }
}
By the way, it feels really accomplishing coming to stackoverflow to get help on debugging a StackOverflowException :)
Related
This question already has answers here:
Inconsistent Accessibility: Parameter type is less accessible than method
(13 answers)
Closed 5 years ago.
My project has 3 classes. A form class with a textbox and a datetimepicker, a class called BuildingPermit and a class called Validator.
I'm using the Validator class to have handle generic data validation such as throwing an error whether or not the text box is blank or has enough characters.
I'd also like like to create a method in the Validator class that compares the values in the text box to a list of values to see if it already exists. I've written the method below and I'm getting an inconsistent accessibility error.
Can you please help me understand why I'm still getting the error when I change the building permit class access to internal? Or would I have to handle the validation directly in the form?
Thanks
public static bool IsUniquePermit(TextBox textbox, List<BuildingPermit> buildingPermitList)
{
foreach (BuildingPermit bp in buildingPermitList)
{
if (textbox.Text == bp.permitNo)
{
MessageBox.Show("That permit number has been previously issued");
return false;
}
else
{
return true;
}
}
}
For reference, the BuildingPermit class is below.
class BuildingPermit
{
DateTime _issuanceDate;
string _permitNo;
public BuildingPermit(DateTime issuanceDate, string permitNo)
{
_issuanceDate = issuanceDate;
_permitNo = permitNo;
}
public DateTime issuanceDate
{
get
{
return _issuanceDate;
}
set
{
_issuanceDate = value;
}
}
public string permitNo
{
get
{
return _permitNo;
}
set
{
_permitNo = value;
}
}
}
}
The default class access level is internal if not specified. Assuming that the class that has the IsUniquePermit method is public, then you're exposing the BuildingPermit class as part of your public API, but the class isn't available. Short answer is to make BuildingPermit public.
More info about it is here: https://stackoverflow.com/a/2521492/149436
You can create an Interface, that is public and keep the class internal.
public interface IBuildingPermit
{
public DateTime issuanceDate
{
get;
set;
}
public string permitNo
{
get;
set;
}
}
Implement it to your class:
class BuildingPermit : IBuildingPermit
{
DateTime _issuanceDate;
string _permitNo;
public BuildingPermit(DateTime issuanceDate, string permitNo)
{
_issuanceDate = issuanceDate;
_permitNo = permitNo;
}
public DateTime issuanceDate
{
get
{
return _issuanceDate;
}
set
{
_issuanceDate = value;
}
}
public string permitNo
{
get
{
return _permitNo;
}
set
{
_permitNo = value;
}
}
}
And change the Method like this:
public static bool IsUniquePermit(TextBox textbox, List<IBuildingPermit> buildingPermitList)
{
foreach (IBuildingPermit bp in buildingPermitList)
{
if (textbox.Text == bp.permitNo)
{
MessageBox.Show("That permit number has been previously issued");
return false;
}
else
{
return true;
}
}
}
I've created a new configuration file Special.config:
<?xml version="1.0" encoding="utf-8"?>
<SpecialConfig xmlns:config="urn:telerik:sitefinity:configuration" xmlns:type="urn:telerik:sitefinity:configuration:type" config:version="10.0.6401.0">
<UnicornSettings HornSize="#{HornSize}" HoofColor="#{HoofColor}" />
</SpecialConfig>
Then followed the documentation to set up a pair of classes (and register the config in the Global.asax.cs) file:
public class SpecialConfig : ConfigSection
{
public UnicornSettingsElement UnicornSettings
{
get
{
return (UnicornSettingsElement)this["UnicornSettings"];
}
set
{
this["UnicornSettings"] = value;
}
}
}
public class UnicornSettingsElement : ConfigElement
{
public UnicornSettingsElement(ConfigElement parent) : base(parent)
{
}
public String HornSize
{
get
{
return (String)this["HornSize"];
}
set
{
this["HornSize"] = value;
}
}
public String HoofColor
{
get
{
return (String)this["HoofColor"];
}
set
{
this["HoofColor"] = value;
}
}
}
But even after explicitly instantiating SpecialConfig.UnicornSettings, it's still null:
UnicornSettings config = Config.Get<UnicornSettings>();
config.UnicornSettings = new UnicornSettingsElement(config);
config.UnicornSettings.HornSize = HornSize; //<-- config.UnicornSettings is null
config.UnicornSettings.HoofColor = HoofColor;
ConfigManager manager = ConfigManager.GetManager();
manager.SaveSection(config);
I have no idea how to overcome this particular exception where the reference is null immediately after being set. Anyone see what I'm missing?
Update
After further fiddling, I think there's something wrong with the getter or setter on the SpecialConfig.UnicornSettings... I'm not sure what that could be though.
DISCLAIMER
I understand what a null reference exception is, and generally speaking how to identify and overcome a null reference exception. This is not a duplicate of a particular C# question whose answer is a very non-specific book of information. This is a particular and precise case involving a specific framework that warrants its own question.
Forgot the ConfigurationProperties. I'm guessing these are necessary for the way the getter/setter accesses properties:
public class SpecialConfig : ConfigSection
{
[ConfigurationProperty("UnicornSettings")]
public UnicornSettingsElement UnicornSettings
{
get
{
return (UnicornSettingsElement)this["UnicornSettings"];
}
set
{
this["UnicornSettings"] = value;
}
}
}
public class UnicornSettingsElement : ConfigElement
{
public UnicornSettingsElement(ConfigElement parent) : base(parent)
{
}
[ConfigurationProperty("HornSize", IsRequired = true)]
public String HornSize
{
get
{
return (String)this["HornSize"];
}
set
{
this["HornSize"] = value;
}
}
[ConfigurationProperty("HoofColor", IsRequired = true)]
public String HoofColor
{
get
{
return (String)this["HoofColor"];
}
set
{
this["HoofColor"] = value;
}
}
}
Just got to know about C# snippet. But i am unable to use them in my code.
Help me out please, I am messed up with get set and how they work.
Here is my test class named "myclass"
namespace WindowsFormsApplication1
{
class myclass
{
public string getmessage(string givenName)
{
return "HB "+givenName;
}
private string bmessage;
public string MyProperty
{
get { return bmessage; }
set { bmessage = value; }
}
}
}
In button code from my form. I am unable to use these get set.
It ll be great if someone clears that how can i use these get set.
Moreover what is "MyProperty" here? I know it is not a method. What is its purpose? Thanks
Snippets itself are not executable statements. But are short-cuts that help you in writing executable statements.
For e.g.
If we write prop and press enter, it will give you a auto-generated property. You just have to change Datatype and Property Name.
Similarly propfull will give a property with get and set parts.
In your case MyProperty is the Property Name and string is the DataType. bmessage is the backing field for your property.
The properties of a class are set and retrieved by using set/get methods. Basically these are also methods.
namespace BusinessObjects
{
public class class_BusinessObjects
{
int StusentId;
string StudentName;
public class_BusinessObjects ()
{
StusentId = 0;
StudentName = string.Empty;
}
public int StusentId
{
get
{
return Id;
}
set
{
Id = value;
}
}
public string StudentName
{
get
{
return Name;
}
set
{
Name = value;
}
}
}
}
using BusinessObjects;
namespace MyModel
{
public class A
{
public class_BusinessObjects Dispaly(int id, string name)
{
class_BusinessObjects obj = new class_BusinessObjects();
obj.StusentId = id;
obj.StudentName = name;
return obj;
}
}
}
I always thought that property is something like shortcut for methods. However this example makes me strange. It seems to me that functions changePropertyId and changeMethodId do the same. However reality is different. Only second one works properly. Can somebody can explain it?
class Program
{
static void Main(string[] args)
{
User user = new User();
user.changePropertyId(1);
Console.Write(user.Id);
user.changeMethodId(1);
Console.Write(user.Id);
Console.ReadLine();
}
}
public class DBObject
{
private int mId;
public int Id { set { mId = Id; } get { return mId; } }
public void setId(int aId)
{mId = aId;}
}
public class User : DBObject
{
public void changePropertyId(int aId) { Id = aId; }
public void changeMethodId(int aId) { setId(aId); }
}
The result from first function is 0, from second is 1. My intention was to get 1 from both.
You have a bug here:
set { mId = Id; }
This should read:
set { mId = value; }
The value is the new value which you should use in a property
setter. Due to this bug basically your setter has no effect.
Here is the fixed version.
public class DBObject
{
private int mId;
public int Id { set { mId = value; } get { return mId; } }
public void setId(int aId) { mId = aId; }
}
Basically they should do the same in your sample. However, there is a little mistake in the property's implementation that you need to correct to make it work:
public int Id { set { mId = value; } get { return mId; } }
value is a reserved name for the parameter of the property setter that contains the new value that should be assigned to the property.
This line is wrong:
public int Id { set { mId = Id; } get { return mId; } }
You're assigning the current property value to the backing field in the setter so you're not actually changing the value. That should read:
public int Id { set { mId = value; } get { return mId; } }
That said, if you're not going to add any code to the getter or setter other than that to return the backing field and set the backing field then you should do away with the backing field altogether and just do this:
public int Id { get; set; }
Note there that I have put the getter before the setter, which is a universal convention and something that you should do too.
Your setter is Invalid: it should be mId = value;. value is a special variable used in setter which contains the value to set.
As is well known, CM doesn't support passing a object of complex type through NavigationService like MVVM Light. So I searched for a workaround and did it like this.
There are two viewmodels: MainPageViewModel and SubPageViewModel.
I first defined 3 classes, namely GlobalData, SnapshotCache and StockSnapshot. StockSnapshot is the type of which the object I want to pass between the 2 viewmodels.
public class SnapshotCache : Dictionary<string, StockSnapshot>
{
public StockSnapshot GetFromCache(string key)
{
if (ContainsKey(key))
return this[key];
return null;
}
}
public class GlobalData
{
private GlobalData()
{
}
private static GlobalData _current;
public static GlobalData Current
{
get
{
if (_current == null)
_current = new GlobalData();
return _current;
}
set { _current = value; }
}
private SnapshotCache _cachedStops;
public SnapshotCache Snapshots
{
get
{
if (_cachedStops == null)
_cachedStops = new SnapshotCache();
return _cachedStops;
}
}
}
public class StockSnapshot
{
public string Symbol { get; set; }
public string Message { get; set; }
}
Next, I call the navigation service on MainPageViewModel like this:
StockSnapshot snap = new StockSnapshot {Symbol="1", Message = "The SampleText is here again!" };
GlobalData.Current.Snapshots[snap.Symbol] = snap;
NavigationService.UriFor<SubPageViewModel>().WithParam(p=>p.Symbol,snap.Symbol).Navigate();
And on SubPageViewModel I've got this:
private string _symbol;
public string Symbol
{
get { return _symbol; }
set
{
_symbol = value;
NotifyOfPropertyChange(() => Symbol);
}
}
public StockSnapshot Snapshot
{
get { return GlobalData.Current.Snapshots[Symbol]; }
}
And that's where the problem lies. When I run the program, I find out that it always runs to the getter of Snapshot first, when Symbol hasn't been initialized yet. So later I've tried adding some extra code to eliminate the ArgumentNullException so that it can run to the setter of Symbol and then everything goes fine except that the UI doesn't get updated anyway.
Could anyone tell me where I've got wrong?
Thx in advance!!
Why not just use:
private string _symbol;
public string Symbol
{
get { return _symbol;}
set
{
_symbol = value;
NotifyOfPropertyChange(() => Symbol);
NotifyOfPropertyChange(() => Snapshot);
}
}
public StockSnapshot Snapshot
{
get { return Symbol!=null? GlobalData.Current.Snapshots[Symbol]:null; }
}
In this case you don't try and get the data from GlobalData when Symbol is null (sensible approach anyway!) and when "Symbol" is set you call NotifyOfPropertyChange() on Snapshot to force a re-get of the property.