This is my property on my code :
public KPage Padre
{
get
{
if (k_oPagina.father != null)
{
this.Padre = new KPage((int)k_oPagina.father);
}
else
{
this.Padre = null;
}
return this.Padre;
}
set { }
}
but it says :
An unhandled exception of type 'System.StackOverflowException' occurred in App_Code.rhj3qeaw.dll
Why? How can I fix it?
EDIT
After correct the code, this is my actual code :
private KPage PadreInterno;
public KPage Padre
{
get
{
if (PadreInterno == null)
{
if (paginaDB.father != null)
{
PadreInterno = new KPage((int)paginaDB.father);
}
else
{
PadreInterno= null;
}
}
return PadreInterno;
}
}
What do you think about?
The property is calling itself... usually properties call underlying fields:
public KPage Padre
{
get
{
if (k_oPagina.father != null)
{
_padre = new KPage((int)k_oPagina.father);
}
else
{
_padre = null;
}
return _padre;
}
set { }
}
private KPage _padre;
Your old code was recursively calling the get of the Padre property, hence the exception.
If your code only "gets" and doesn't need to store the value, you could also get rid of the backing field entirely:
public KPage Padre
{
get
{
return k_oPagina.father != null
? new KPage((int)k_oPagina.father)
: (KPage)null;
}
}
That said, I'd put this in a method.
This is also the same issue as the one you asked a couple of days ago:
An unhandled exception of type 'System.StackOverflowException' occurred
Related
I have a custom class that gets some data from the web.
When I get this data I want to set it to the value of a property but when I do this unity crashes. The commented line generates the crash without this line everything works fine. See my code below:
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class GetDB
{
private readonly Main m;
private readonly string Url;
public string DBData {
get
{
if(DBData == null)
return null;
else
return DBData;
}
private set
{
DBData = value;
}
}
public GetDB(Main m, string url)
{
this.m = m;
this.Url = url;
}
public void GetServerData(){
m.StartCoroutine(GetText(Url, (result) =>{
this.DBData = result; //THIS LINE CRASHES UNITY
Debug.Log(result);
}));
}
IEnumerator GetText(string url, Action<string> result) {
UnityWebRequest www = UnityWebRequest.Get(url);
yield return www.SendWebRequest();
if(www.isNetworkError || www.isHttpError) {
Debug.Log(www.error);
}
else {
if (result != null)
result(www.downloadHandler.text);
}
}
}
How would I go about fixing this, and what exactly is happening here?
If anything is unclear let me know so I can clarify.
You have to use a backing field for the property:
string _dbData;
public string DBData
{
get
{
if(_dbData == null)
return null;
else
return _dbData;
}
private set
{
_dbData= value;
}
}
A property is just syntactic sugar for a getter and setter methods. So you can rewrite your property like:
public string GetDBData()
{
if(_dbData == null)
return null;
else
return _dbData;
}
public void SetDBData(string value)
{
_dbData = value;
}
The way you have implemented the property:
public void SetDBData(string value)
{
// you will never get out of here
SetDBData(value);
}
Properties act as accessors for variables. What is happening in your case is basically an endless loop - whenever somebody tries to get the value of your property, it keeps returning the property itself. Instead, you want a backing field _dbData:
private string _dbData;
public string DBData
{
get
{
return _dbData;
}
private set
{
_dbData = value;
}
}
Now your property controls the accesss to this field.
Your accessor can be really simplified.
Doing :
get
{
if(DBData == null)
return null;
else
return DBData;
}
Will provide exactly the same result than doing :
get
{
return DBData; //if DBData is null, it will return null
}
So, you can write your accessor that way :
public string DBData
{
get;
private set;
}
We are using HttpSessionStateBase to store messages in a set up similar to this working example:
public class HttpSessionMessageDisplayFetch : IMessageDisplayFetch
{
protected HttpSessionStateBase _session;
private IList<ICoreMessage> messages
{
get
{
if (_session[EchoCoreConstants.MESSAGE_KEY] == null)
_session[EchoCoreConstants.MESSAGE_KEY] = new List<ICoreMessage>();
return _session[EchoCoreConstants.MESSAGE_KEY] as IList<ICoreMessage>;
}
}
public HttpSessionMessageDisplayFetch()
{
if (HttpContext.Current != null)
_session = new HttpSessionStateWrapper(HttpContext.Current.Session);
}
public void AddMessage(ICoreMessage message)
{
if (message != null)
messages.Add(message);
}
public IEnumerable<IResultPresentation> FlushMessagesAsPresentations(IResultFormatter formatter)
{
var mToReturn = messages.Select(m => m.GetPresentation(formatter)).ToList();
messages.Clear();
return mToReturn;
}
}
When we pass in a QualityExplicitlySetMessage (which inherits from ICoreMessage, see below) it is saved correctly to messages.
This is how the object looks after being inserted into the messages list, at the end of AddMessage(ICoreMessage message) above.
But when we come to access it after changing controllers the inherited member's properties are null, which causes a variety of null reference exceptions.
This is how the object now looks after we call FlushMessagesAsPresentations. I've commented out var mToReturn... as this tries to access one of these null ref properties.
I'd like to ask the following:
Why is the HttpSessionStateBase failing to capture these values taken
by the inherited type?
Is this an issue in saving to the HttpSession or in retrieving?
Is this anything to do with, as I suspect, inheritance?
Or is the fact I'm potentially calling a new controller that dependency injects the HttpSessionMessageDisplayFetch causing an issue?
I'm a first-time poster so please let me know if I'm making any kind of faux pas - Super keen to learn! Any input is very welcome.
Some potentially useful code snippets:
QualityExplicitlySetMessage
public class QualityExplicitlySetMessage : QualityChangeMessage
{
public QualityExplicitlySetMessage(IQPossession before, IQPossession after, IQEffect qEffect)
: base(before, after, qEffect)
{
IsSetToExactly = true;
}
}
QualityChangeMessage - Working example
public abstract class QualityChangeMessage : CoreMessage, IQualityChangeMessage
{
protected PossessionChange Change;
public PossessionChange GetPossessionChange()
{
return Change;
}
protected QualityChangeMessage(IQPossession before, IQPossession after, IQEffect qEffect)
{
Change = new PossessionChange(before, after, qEffect);
StoreQualityInfo(qEffect.AssociatedQuality);
}
public override IResultPresentation GetPresentation(IResultFormatter formatter)
{
return formatter.GetQualityResult(this);
}
#region IQualityChangeMessage implementation
public int LevelBefore
{
get { return Change.Before.Level; }
}
//... And so on with values dependent on the Change property.
}
CoreMessage - Working example
public abstract class CoreMessage : ICoreMessage
{
public string MessageType
{
get { return GetType().ToString(); }
}
public string ImageTooltip
{
get { return _imagetooltip; }
set { _imagetooltip = value; }
}
public string Image
{
get { return _image; }
set { _image = value; }
}
public int? RelevantQualityId { get; set; }
protected void StoreQualityInfo(Quality q)
{
PyramidNumberIncreaseLimit = q.PyramidNumberIncreaseLimit;
RelevantQualityId = q.Id;
RelevantQualityName = q.Name;
ImageTooltip = "<strong>" + q.Name + "</strong><br/>" + q.Description + "<br>" +
q.EnhancementsDescription;
Image = q.Image;
}
public virtual IResultPresentation GetPresentation(IResultFormatter formatter)
{
return formatter.GetResult(this);
}
}
UserController - Working example.
public partial class UserController : Controller
{
private readonly IMessageDisplayFetch _messageDisplayFetch;
public UserController(IMessageDisplayFetch messageDisplayFetch)
{
_messageDisplayFetch = messageDisplayFetch;
}
public virtual ActionResult MessagesForStoryletWindow()
{
var activeChar = _us.CurrentCharacter();
IEnumerable<IResultPresentation> messages;
messages = _messageDisplayFetch.FlushMessagesAsPresentations(_storyFormatter);
var vd = new MessagesViewData(messages)
{
Character = new CharacterViewData(activeChar),
};
return View(Views.Messages, vd);
}
}
I have class library which is already developed and in it the following code has been written,
public static PersistenceManager Instance
{
get
{
if (_instance == null)
{
_instance = new PersistenceManager();
}
return _instance;
}
}
where PersistenceManager is a class. I have a WPF application in which i am calling this dll and just before showing login page there is a code written as below,
if (string.IsNullOrWhiteSpace(PersistenceManager.Instance["user"]))
{
StartupUri = new Uri("Login.xaml", UriKind.Relative);
}
else
{
StartupUri = new Uri("Messenger.xaml", UriKind.Relative);
}
I have already registered so it always shows messanger window. Now i want to clear the keyvalue of user so that i can show the login page. I am unable to perform below code ,
PersistenceManager.Instance["user"] = string.Empty;
An unhandled exception of type 'System.ArgumentException' occurred
Any suggesions?
Index-Operator looks like:
public string this[string key]
{
get
{
try
{
return _settingsDictionary[key].Decrypt(ENCKEY);
}
catch (Exception)
{
return string.Empty;
}
}
set
{
if(!string.IsNullOrWhiteSpace(key))
_settingsDictionary[key] = value.Encrypt(ENCKEY);
}
}
rewrite the index operator as following:
public string this[string key]
{
get
{
string value;
_settingsDictionary.TryGetValue(key, out value);
if (string.IsNullOrEmpty(value)) return string.Empty;
return value.Decrypt(ENCKEY);
}
set
{
if (string.IsNullOrEmpty(value)) _settingsDictionary.Remove(key);
else _settingsDictionary[key] = value.Encrypt(ENCKEY);
}
}
I am trying to adapt singleton policy for my CsvConfiguration Property.
If the configuration is already available, just return the configuration. else, get the configuration and return the same and I am able to build this code.
public Rootpdf pdfConfiguration
{
get
{
Rootpdf pdfConfiguration = null;
try
{
if (pdfConfiguration == null)
{
//retrieve the configuration file.
//load the configuration and return it!
}
else
{
return pdfConfiguration;
}
}
catch (Exception e)
{
Log.Error("An error occurred while reading the configuration file.", e);
}
return pdfConfiguration;
}
}
Advantages (i hope): Whenever my pdfConfiguration is wanted, if already it is available, i can return it. Need not load the configuration file eachtime
and calculate the configuration.
My Query: The resharper! The resharper tells that the code
if (pdfConfiguration == null) //The expression is always true.
Is it really a problem with resharper that it doesn't understand I am following this singleton pattern ?
or
Am I not following singleton pattern at all?
You're setting the singleton to null at the top of your get clause:
Rootpdf pdfConfiguration = null;
//THIS IS THE PROBLEM.
Note: 99% of the time, ReSharper is smarter than you. I don't like it, but it's true.
think you have to use a local variable out of the getter
private static Rootpdf _pdfConfiguration ;
public static Rootpdf pdfConfiguration
{
get
{
try
{
if (_pdfConfiguration == null)
{
//retrieve the configuration file.
//load the configuration and return it!
}
else
{
return _pdfConfiguration;
}
}
catch (Exception e)
{
Log.Error("An error occurred while reading the configuration file.", e);
}
return _pdfConfiguration;
}
}
and as you want a singleton, i made it a static property... hope it's what you need.
Here is what your class should look like:
public class RootPdf
{
private static RootPdf instance;
private RootPdf()
{
//retrieve the configuration file.
//load the configuration and return it!
}
public static RootPdf Instance
{
get
{
if (instance == null)
{
try
{
instance = new RootPdf();
}
catch (Exception e)
{
Log.Error("An error occurred while reading the configuration file.", e);
return null;
}
}
return instance;
}
}
}
And here is how you will call the object:
var pdf = RootPdf.Instance;
class MySingletonClass
{
private static UserSettings instance = null;
/// <summary>
/// Default protected constructor.
/// </summary>
protected MySingletonClass()
{
}
/// <summary>
/// Invoke the singleton instance.
/// </summary>
public static MySingletonClass Instance()
{
if (instance == null)
instance = new MySingletonClass();
return instance;
}
}
This woud be invoked/instanciated like
MySingletonClass msc = MySingletonClass.Instance();
You can also use an accessor/Property to return the instance
public MySingletonInstance Instance
{
get
{
if (instance == null)
instance = new MySingletonInstance();
return instance;
}
}
Where this is invoked/instantiated via
MySingletonClass msc = MySingletonClass.Instance;
I like the first method of the above.
I hope this helps.
As already mentioned this is a not a singleton pattern.
If you want to stick with the idea you described then I would change your code to :
internal class Config
{
private readonly Lazy<Rootpdf> _config;
public Config()
{
_config = new Lazy<Rootpdf>(ReadConfiguration);
}
private Rootpdf ReadConfiguration()
{
throw new NotImplementedException();
}
public Rootpdf pdfConfiguration
{
get
{
try
{
return _config.Value;
}
catch (Exception e)
{
Log.Error("An error occurred while reading the configuration file.", e);
}
return null;
}
}
This line: if (pdfConfiguration == null) will always be true due to this line (just before) Rootpdf pdfConfiguration = null;. What you need to do is to place the last line (Rootpdf pdfConfiguration = null;) outside the Get method. This will stop the variable to be initialized to null each time.
private static Rootpdf pdfConfiguration = null;
public Rootpdf PdfConfiguration
{
get
{
try
{
if (pdfConfiguration == null)
....
More information on the Singleton Pattern is available here.
Alternatively, you can use a Static Constructor:
A static constructor is used to initialize any static data, or to
perform a particular action that needs to be performed once only. It
is called automatically before the first instance is created or any
static members are referenced.
public class Foo {
private static Rootpdf pdfConfiguration = null;
static Foo()
{
pdfConfiguration = ....
}
public Rootpdf pdfConfiguration
{
get
{
return pdfConfiguration;
}
....
Nowadays , I think since C# 6.0, you can use initial values with properties, like this:
static public Rootpdf pdfConfiguration { get; } = new Func<Rootpdf>(() => {
//retrieve the configuration file.
//load the configuration and return it!
return new Rootpdf(); // Something like this perhaps..?
})();
I hope to phrase my question correctly (if not please help me to entitle it better)
,to make it clear,please take a look at my code.
class Factory
{
public string Name { get; set; }
private Person _manager;
public Person Manager
{
get
{
return (_manager );
}
set
{
_manager = value;
if (_manager.WorkPlace!=this)
{
_manager.WorkPlace = this;
}
}
}
public Factory(string name, Person manager)
{
Name = name;
Manager = manager;
if (Manager.WorkPlace ==null)
{
Manager.WorkPlace = this;
}
}
public Factory(string name, string managerFullName, int managerAge)
{
Name = name;
Manager = new Person(managerFullName, managerAge);
if (Manager.WorkPlace != this)
{
Manager.WorkPlace = this;
}
}
public void ShowInfo()
{...}
}
my problem appears when using first constructor of factory class
class Program
{
static void Main(string[] args)
{
Person oPerson1=new Person("Jon",30);
factory oFactory1=new Factory("f1",oPerson1);
factory oFactory2=new Factory("f2",oPerson1);
factory oFactory3=new Factory("f3",oPerson1);
factory oFactory4=new Factory("f4",oPerson1);
...
}
}
as you can see in this constructor I can use one person object(as a manger) more than one time
,in fact so many times it could be used , and there is nothing to prevent me . that
means one person could manage many factories,I dont want it.I want a person could
mange only one factory,how is that possible?
to handle this issue some workarounds came to my mind.
1- deleting that constructor and using only another one .(but I am looking for a better solution,I would like to have that constructor.)
2- throwing an exception in Run time that i hate it
as i know the c# compiler has nothing to prevent passing an object more than one time.
should I change something in design of the class?
what is your recommendation? what is the best solution ?thank u so much for any advices.
EDIT:Our business Logic
each factory has a manager ,its meaningless to have a factory without a manger.
and a person could be a manager.
person(1..1)-------------(0..1)factory
Relationships are better modeled with static code relationships than with imperative checks. That would enable the compiler to help you enforce the relationship.
Remove the manager from the factory and add the factory to the manager:
public class Manager : Person
{
public Manager(Factory factory)
}
In this way a Manager can manage only one Factory...
The answer is in your code:
set
{
_manager = value;
if (_manager.WorkPlace!=this)
{
_manager.WorkPlace = this;
}
}
Replace this with
set
{
if (value == null) // Edit: Add manager release capability to change factories
{
if(_manager != null)
_manager.WorkPlace = null;
_manager = null;
}
else if (value.WorkPlace == null)
{
_manager = value;
_manager.WorkPlace = this;
}
else
throw new ArgumentException();
}
I use the following "micropattern" for setters:
public Person Manager
{
get
{
return (_manager );
}
set
{
if (_manager != null)
{
_manager.WorkPlace = null;
}
_manager = value;
if (_manager != null)
{
_manager.WorkPlace = this;
}
}
Now, whenever you associate a manager with a factory, it's old manager is automatically de-associated with the factory.
Now, this does not prevent you reassigning a manager to a factory. But it will make sure that pointers are always in sync with each other.
I learned this trick from Martin Fowlers Refactoring. An online reference to the technique can be found here.
Despite that you hate it, throwing an exception in the constructor will notify you early that you have an error. You also need to make sure that the Person isn't already a manager.
public Factory(string name, Person manager)
{ if (Manager.WorkPlace != null && Manager.WorkPlace.Manager==manager)
{
var errmsg = "Cannot pass an existing manager to Factory constructor.";
throw new ArgumentException("manager",errmsg);
}
Name = name;
Manager = manager;
Manager.WorkPlace = this;
}
A "Cell" has an "Item"; and an "Item" has a "Cell". If you update one of them; the other should be updated as well. So In Cell we have a property like:
public Item CurrentItem
{
get { return _currentItem; }
set
{
if (_currentItem == value) return;
var oldItem = _currentItem;
_currentItem = value;
if (oldItem != null && oldItem.CurrentCell == this)
{
oldItem.CurrentCell = null;
}
if (value != null)
{
value.CurrentCell = this;
}
}
}
In the opposite site (In Item) we have following property:
public Cell CurrentCell
{
get { return _currentCell; }
set
{
if (_currentCell == value) return;
var oldCell = _currentCell;
_currentCell = value;
if (oldCell != null && oldCell.CurrentItem == this)
{
oldCell.CurrentItem = null;
}
if (value != null)
{
value.CurrentItem = this;
}
}
}