What wrong with Dictionary in property of class? - c#

Why is this code not working?
public class A
{
public Dictionary<int, string> dic { get; set; }
}
class Program
{
public static void Main()
{
A a = new A();
a.dic.Add(1, "a");
}
}
Error:
System.NullReferenceException was unhandled
Message=Object reference not set to an instance of an object.

You haven't initialized the property, so the value of a.dic is null (the default for any reference type).
You'd need something like:
a.dic = new Dictionary<int, string>();
... or you could initialize it in the constructor.
On the other hand, it's rarely a good idea to have such direct access to the inner workings of a class - you basically have no encapsulation here.

Dictionary is a reference type. It's default value is null. There's no "new Dictionary" anywhere in your program; there probably should be.

public class A
{ public Dictionary dic;
A()
{
dic = new Dictionary();
}
}
class Program
{ public static void Main() { A a = new A(); a.dic.Add(1, "a");
}
}

Change the definition of A to something like this:
public class A
{
public Dictionary<int, string> dic { get; set; }
public A()
{
dic = new Dictionary<int, string>();
}
}
The key point is that you need to initialize the "dic" property before you can use it.

Related

Generic class and method binding with delegates(or not) for clean method expression

Lets say you have simple chained method but you are trying to access or set a value in a class property (internal/external doesnt matter). Using a Func seems to be working and finds the relation between generic class that is passed and access its properties correctly but i am not sure if its necessary.
Is there a way of setting the method variable cleanly as in Main method below since it is aware of the Generic class association without doing new Props().Property for example?
//sample console app
public class Props {
public string FirstProp = "lets say object";
public string SecondProp = "Pretend some other object";
}
public class Logic<T> where T : class, new()
{
private string outString { get; set; }
public Logic<T> GetPropertyValue(Func<T, object> propertySelector)
{
return this;
}
public Logic<T> GetLambda(Expression<Func<T, object>> propertySelector)
{
var breakpointCheck = propertySelector; //{x => x.SecondProp}
return this;
}
}
class Program
{
static void Main(string[] args)
{
var Test =
new Logic<Props>()
.GetPropertyValue(x => x.FirstProp) //dummy check
.GetLambda(x => x.SecondProp); //passed correctly {x => x.SecondProp}
var HowToGetThis =
new Logic<Props>()
.GetPropertyValue(FirstProp) // or GetPropertyValue(Props.FirstProp)
.GetLambda(x => x.SecondProp);
}
}

Dictionary inherited from base class cannot be added to from derived class

I have an abstract class for POs.
public abstract class PO
{
public abstract Dictionary<string, object> InvalidFields { get; }
public abstract string PONumber { get; set; }
}
Which is inherited by two different types of PO: CPO and POR.
public class CPO
{
private string poNumber;
public override Dictionary<string, object> InvalidFields => new Dictionary<string, object>();
public override string PONumber
{
get
{
return poNumber;
}
set
{
if (!ValidatePONumber(value)) InvalidFields.Add("CPO Number", value);
poNumber = value;
}
}
}
When ValidatePONumber(value) returns false, it correctly executes InvalidFields.Add() but the dictionary is never actually added to. In the Locals window, a new variable is created named Namespace.PO.InvalidFields.get returned and I can see the new key that is added. However, this.InvalidFields has no values.
So it looks like the dict in the abstract base class PO is being created and added to instead of the derived class CPO.
Thanks to Klaus for pointing out the issue. I resolved by setting up a private invalidFields field and returning that with InvalidFields.get because what I was doing was returning a new Dictionary class with every get.
public class CPO : PO
{
private string poNumber;
private Dictionary<string, object> invalidFields = new Dictionary<string, object>();
public override Dictionary<string, object> InvalidFields { get => invalidFields; }
public override PONumber
{
get
{
return poNumber;
}
set
{
if (!ValidatePONumber(value)) InvalidFields.Add("CPO Number", value);
poNumber = value;
}
}
}
The code as you have given above does not even compile. You derived class is not actually inheriting from the abstract class (I am assuming it is a typo). Even after addition abstract class, the dictionary instantiation throws an error because it is a property definition and missing 'set' definition (InvalidFields is missing 'set' accessor definition.
Also, this sounds to be a duplicate of Overriding fields or properties in subclasses
I have tried this with minor modifications, please see the code below. Like #yransis says in comments, The InvalidFields is being treated as a 'get' property, returning new instance of dictionary every time it is executing the 'Add' step.
class DerivedCpo : AbstractPo
{
private string poNumber;
private Dictionary<string, object> invalidFieldsBackingField;
public override Dictionary<string, object> InvalidFields
{
get
{
return invalidFieldsBackingField;
}
set { this.invalidFieldsBackingField = value; }
}
public DerivedCpo()
{
this.InvalidFields = new Dictionary<string, object>();
}
public override string PoNumber
{
get { return poNumber;}
set
{
if(!ValidatePONumber((value)))
InvalidFields.Add("CPO Number", value);
poNumber = value;
}
}
private bool ValidatePONumber(string value)
{
if (string.IsNullOrEmpty(value))
{
return false;
}
if (value.Length > 5)
return false;
return true;
}
}
Main method calling this class -
static void Main(string[] args)
{
var po = new DerivedCpo();
po.PoNumber = "test1";
po.PoNumber = "thisistheinvalidfieldpo";
if (po.InvalidFields != null && po.InvalidFields.Count > 0)
{
Console.WriteLine(#"There are {0} fields in invalidFields collection", Convert.ToString(po.InvalidFields.Count) );
}
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
In the code above I have added explicit backing field. It is being instantiated only once in the constructor. That way the contents of InvalidFields are persistent. In your code, you are returning a new instance of dictionary, essentially losing the data that was stored between two 'get' calls.

Creating a read only generic List from a derived class

I'm developing a library for developers where they have to create a class that inherits from a class I created.
This base class essentially manages an array of objects for the developer, however the developer gets to specify the type of these objects they want the base class to manage.
So the developer essentially just tells the base class to create an array, then only has read only access to that array. The base class will (depending on the state of the application) add or remove objects from the array.
I'm stuck at finding the right data type to store such a thing. I've tried ref and out but that got me nowhere. The closest I got was with a Dictionary but that idea fell apart because C# is actually just copying the value into the dictionary instead of referencing or pointing to it.
Here is a quick example I threw together:
public static void Main()
{
Derived d = new Derived();
d.InitBase();
d.Init();
d.CheckArray();
d.AddElement<GenericObject>(new GenericObject{ i = 2 });
d.CheckArray();
}
public class Base {
Dictionary<Type, List<object>> ArrayReferences;
public void InitBase() {
ArrayReferences = new Dictionary<Type, List<object>>();
}
protected ReadOnlyCollection<T> RegisterArray<T>() {
List<object> managedArray = new List<object>();
ArrayReferences.Add(typeof(T), managedArray);
return Array.AsReadOnly(managedArray.Select(s => (T)s).ToArray());
}
public void AddElement<T>(T obj) {
ArrayReferences[typeof(T)].Add(obj);
}
public void RemoveElement<T>(T obj) {
ArrayReferences[typeof(T)].Remove(obj);
}
}
public class Derived: Base {
ReadOnlyCollection<GenericObject> arr;
public void Init() {
arr = RegisterArray<GenericObject>();
}
public void CheckArray() {
Console.WriteLine(arr.Count());
}
}
public class GenericObject {
public int i = 0;
}
Output:
0
0
Dictionary obviously doesn't store the values as references like I want it to. So what other technique does C# have or is this simply not possible? Also not sure how many issues unsafe will cause me so I'm scared going that route.
While I think there are better ways of handling this issue, this can be done.
Instead of storing a List<object> reference, which isn't compatible with a List<T>, store an object. Use a static in Base to hold the Dictionary so there is one Dictionary for all derived classes.
public static void Main() {
var d = new Derived();
d.CheckCollection("d before AddElement");
d.AddElement(new GenericObject { i = 2 });
d.CheckCollection("d after AddElement");
Console.WriteLine($"ListCount = {Base.ListCount}");
var d2 = new Derived2();
d2.CheckCollection("d2 before AddElement");
d2.AddElement(new GenericObject2 { i = 4 });
d2.AddElement(new GenericObject2 { i = 5 });
d2.CheckCollection("d2 after AddElement");
Console.WriteLine($"ListCount = {Base.ListCount}");
}
public class Base {
static Dictionary<Type, object> ListReferences = new Dictionary<Type, object>();
public static int ListCount => ListReferences.Count();
protected ReadOnlyCollection<T> RegisterList<T>() {
var managedList = new List<T>();
ListReferences.Add(typeof(T), managedList);
return managedList.AsReadOnly();
}
public void AddElement<T>(T obj) {
((List<T>)ListReferences[typeof(T)]).Add(obj);
}
public void RemoveElement<T>(T obj) {
((List<T>)ListReferences[typeof(T)]).Remove(obj);
}
}
public class Derived : Base {
ReadOnlyCollection<GenericObject> roc;
public Derived() {
roc = RegisterList<GenericObject>();
}
public void CheckCollection(string msg) {
Console.WriteLine(msg);
Console.WriteLine(roc.Count());
}
}
public class Derived2 : Base {
ReadOnlyCollection<GenericObject2> roc;
public Derived2() {
roc = RegisterList<GenericObject2>();
}
public void CheckCollection(string msg) {
Console.WriteLine(msg);
Console.WriteLine(roc.Count());
}
}
public class GenericObject {
public int i = 0;
}
public class GenericObject2 {
public int i = 0;
}
PS Also, don't name methods and variables with "array" when you are using Lists.
The following code you've written makes a copy of your list at the time you created it - so it is always empty, no matter what you add to the list afterwards.
List<object> managedArray = new List<object>();
ArrayReferences.Add(typeof(T), managedArray);
return Array.AsReadOnly(managedArray.Select(s => (T)s).ToArray());
Here is how you should write your code to get what you want:
public static void Main()
{
Derived d = new Derived();
Console.WriteLine(d.AsReadOnly().Count);
d.AddElement(new GenericObject { i = 2 });
Console.WriteLine(d.AsReadOnly().Count);
}
public class Base<T>
{
List<T> _items = new List<T>();
public ReadOnlyCollection<T> AsReadOnly()
{
return Array.AsReadOnly(_items.ToArray());
}
public void AddElement(T obj)
{
_items.Add(obj);
}
public void RemoveElement(T obj)
{
_items.Remove(obj);
}
}
public class Derived : Base<GenericObject>
{
}
public class GenericObject
{
public int i = 0;
}
That outputs:
0
1
Now, it's worth considering that List<T> already has a AsReadOnly() method, so you could simply write this:
public static void Main()
{
var d = new List<GenericObject>();
Console.WriteLine(d.AsReadOnly().Count);
d.Add(new GenericObject { i = 2 });
Console.WriteLine(d.AsReadOnly().Count);
}
public class GenericObject
{
public int i = 0;
}
That works too.
Here's how you should do this to hold more than one list at a time. There's no need for inheritance.
public static void Main()
{
Repository r = new Repository();
Console.WriteLine(r.AsReadOnly<GenericObject>().Count);
r.AddElement<GenericObject>(new GenericObject { i = 2 });
Console.WriteLine(r.AsReadOnly<GenericObject>().Count);
}
public class Repository
{
private Dictionary<Type, object> _references = new Dictionary<Type, object>();
private void Ensure<T>()
{
if (!_references.ContainsKey(typeof(T)))
{
_references[typeof(T)] = new List<T>();
}
}
public ReadOnlyCollection<T> AsReadOnly<T>()
{
this.Ensure<T>();
return (_references[typeof(T)] as List<T>).AsReadOnly();
}
public void AddElement<T>(T obj)
{
this.Ensure<T>();
(_references[typeof(T)] as List<T>).Add(obj);
}
public void RemoveElement<T>(T obj)
{
this.Ensure<T>();
(_references[typeof(T)] as List<T>).Remove(obj);
}
}
public class GenericObject
{
public int i = 0;
}
In your base (or encapsulated class if you choose to go that way):
protected ReadOnlyCollection<T> GetSnapshot<T>() {
return Array.AsReadOnly(ArrayReferences[typeof(T)].Select(s => (T)s).ToArray());
}
Then you'd also add any other methods to view the data, e.g. to get a count:
protected int GetCount<T>() {
return ArrayReferences[typeof(T)].Count;
}

How this way of defining properties is called

public class TestClass
{
private Dictionary<string, int> _testDictionary = new Dictionary<string,int>();
private string _key;
public int this[string key]
{
get { return _testDictionary[key];}
set
{
if (_testDictionary.ContainsKey(key))
_testDictionary[key] = value;
else
_testDictionary.Add(key, value);
}
}
}
public class Program
{
static void Main(string[] args)
{
TestClass test = new TestClass();
test["T1"] = 1;
test["T2"] = 2;
Console.WriteLine(test["T1"]);
Console.WriteLine(test["T2"]);
}
}
So how this way of defining properties is called, I want to read more about that. Also is it possible to have same definition like this in other places, for an example in Methods etc.
Your implementation is right, you could add your desired IndexerName but you don't have to. It is better to add a guide from the getter in case the key is not found, and you return some default value.
Check out this enter link description here
public class TestClass
{
private Dictionary<string, int> _testDictionary = new Dictionary<string, int>();
// you do not need a private property to store the key
// private string _key;
[IndexerName("MyKeyItem")]
public int this[string key]
{
get
{
if (_testDictionary.ContainsKey(key))
{
return _testDictionary[key];
}
return int.MinValue;
}
set
{
if (_testDictionary.ContainsKey(key))
_testDictionary[key] = value;
else
_testDictionary.Add(key, value);
}
}
}
It's called an indexed property.

Initialize list with default values

I want to have a class, that stores all "allowed languages" in a list. Code party should be able to modify the list. But on first usage, the list should be "initialized" with some default values.
I have the following class:
public class ApiLanguages
{
public static List<string> AllowedLanguages { get; set; }
public ApiLanguages()
{
AllowedLanguages.Add("de");
//AllowedLanguages.Add("en");
//AllowedLanguages.Add("es");
//AllowedLanguages.Add("fr");
//AllowedLanguages.Add("it");
}
}
When I access the class now in code with
foreach (var language in ApiLanguages.AllowedLanguages)
{
// do something here...
}
the ApiLanguages.AllowedLanguages is null. But I expect one entry ("de"). What I am doing wrong here?
public ApiLanguages() is an instance constructor. It runs only (and every time) when you create a new instance of ApiLanguages (via new ApiLanguages()). It's purpose is to initialize instance variables, not static ones. You usually shouldn't initialize static properties or fields in an instance constructor.
You need to use the static constructor to initialize the static list like this:
public class ApiLanguages
{
public static List<string> AllowedLanguages { get; set; }
static ApiLanguages()
{
AllowedLanguages = new List<string>();
AllowedLanguages.Add("de");
//...
}
}
You can make your constructor static as well, but I prefer lazy loading. By this you will not populate list again and again whenever object is created of ApiLanguages,
public class ApiLanguages
{
private static IEnumerable<string> _allowedLanguages;
public static IEnumerable<string> AllowedLanguages
{
get
{
return _allowedLangues ?? (_allowedLangues = new List<string>{ "EN", "AR"});
}
}
}
You should initialize AllowedLanguages with new instance of List<string> first. You can do it with initializers for auto-properties in c# 6.0 or in the static constructor for older versions of c#.
public class ApiLanguages
{
// c# 6.0 syntax
public static List<string> AllowedLanguages { get; set; } = new List<string>();
static ApiLanguages()
{
// c# < 6.0 (old style) syntax
AllowedLanguages = new List<string>();
}
public ApiLanguages()
{
AllowedLanguages.Add("de");
}
}
Also I'm sure that you no need to add new values to the list for each instance of ApiLanguages class then you should move AllowedLanguages.Add(...) to the static constructor too. And you can join object creation and initialization to a single line of code:
public static List<string> AllowedLanguages { get; set; } = new List<string>() { "de", "en", "ru" };

Categories