.NET Serialization getters and setters - c#

I want to try a .NET deserialization example, but it seems I am not able to get the getters and setters working. This is my code
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
namespace WindowsFormsApplication3
{
[XmlRoot]
public class TestClass
{
public string classname;
private string name;
private int age;
[XmlAttribute]
public string Classname { get => classname; set => classname = value; }
[XmlElement]
public string Name { get => name; set => name = value; }
[XmlElement]
public int Age { get=>age; set => age = value; }
public override string ToString()
{
return base.ToString();
}
}
class Program
{
static void Main(string[] args)
{
TestClass testClass = new TestClass();
testClass.Classname = "test";
testClass.Name = "william";
testClass.Age = 50;
Console.WriteLine("Hello World!");
MessageBox.Show("Test");
}
}
}
And I get the following error in the get declaration: Not all code paths return a value

As commented by #CodeCaster, you need a minimum of C# 7.0 to work around on Expression-Bodied Members and your visual studio doesn't support it.
So you can upgrade your visual studio to C# 7.0 or use below with current version,
You can use
public string Classname
{
get { return classname; }
set { classname = value; }
}
instead of
public string Classname
{
get => classname;
set => classname = value;
}
And do the same for all other remaining properties in your class those are with expression-bodies.

Related

c# Full Name of Property in Class

I have a class
public class MyCoolProp
{
public string FullName {get;set;}
}
and in another Class i have this as Property:
public class MyMainClass
{
public MyCoolProp coolprop {get;set;}
public void DoSomething()
{
MessageBox.Show(nameof(coolprop.FullName));
}
}
The Actual Result is: "Fullname"
But i want a combination like this: "coolprop.FullName"
i dont want to do something like this:
nameof(coolprop) + "." + nameof(coolprop.FullName);
Maybe its possible in an extension?
If i rename the Property "coolprop" the output should also have the new name
Depending on exactly what you want to do, you might be able to use CallerArgumentExpressionAttribute. That does mean you need to be willing to actually evaluate the property as well, even if you don't use it.
Note that this requires a C# 10 compiler.
Here's a complete example:
using System.Runtime.CompilerServices;
public class MyCoolProp
{
public string FullName { get; set; }
}
class Program
{
static MyCoolProp CoolProp { get; set; }
static void Main()
{
CoolProp = new MyCoolProp { FullName = "Test" };
WriteTextAndExpression(CoolProp.FullName);
}
static void WriteTextAndExpression(string text,
[CallerArgumentExpression("text")] string expression = null)
{
Console.WriteLine($"{expression} = {text}");
}
}
Output: CoolProp.FullName = Test
Source:
get name of a variable or parameter (modified a bit adjusted with your case)
You can use what System.Linq.Expression provides
code example:
using System.Linq.Expression
class Program
{
public static MyCoolProp coolProp { get; set; }
static void Main(string[] args)
{
coolProp = new MyCoolProp() { FullName = "John" };
DoSomething();
}
public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
{
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
return expressionBody.ToString();
}
public static void DoSomething()
{
string prop = GetMemberName(() => coolProp.FullName);
Console.WriteLine(prop);
}
}
public class MyCoolProp
{
public string FullName { get; set; }
}
the GetMemberName method will return the namespace, class name, object name, and variable name (depends where the method is being called)
Output: Program.coolProp.FullName

How to check if an object has default values in C#

I have an object that I want to check whether it contains default values or not, in the below code but that doesn't cut it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
MyClass obj1 = new MyClass();
MyClass obj2 = null;
if(obj1 == new MyClass())
Console.WriteLine("Initialized");
if(Object.ReferenceEquals(obj1, new MyClass()))
Console.WriteLine("Initialized");
}
}
}
public class MyClass
{
public int Value {get; set; }
public MyClass()
{
this.Value = 10;
}
}
I have also used Object.ReferenceEquals() but that doesn't cut it as well.
This is the fiddle I am working on.
Is there a way to check whether an object contains default values, or if the object is empty?
Edit: In case of an newly initialized object with many nested properties, how to check whether they contain a default value or not?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
MyClass obj1 = new MyClass();
MyClass obj2 = null;
if(obj1 == new MyClass())
Console.WriteLine("Initialized");
if(Object.ReferenceEquals(obj1, new MyClass()))
Console.WriteLine("Initialized");
}
}
}
public class MyClass
{
public int Value {get; set; }
public MyNestedClass MyProperty { get; set; }
public MyClass()
{
this.Value = 10;
this.MyProperty = new MyNestedClass();
}
}
public class MyNestedClass
{
public string SomeStringProperty { get; set; }
public MyNestedClass()
{
this.SomeStringProperty = "Some string";
}
}
Here is the fiddle in the case of nested objects.
You can achieve your goal by overriding Equals and GetHashCode, creating and saving an immutable "default" instance, and comparing the value to it:
public class MyClass {
public static readonly MyClass DefaultInstance = new MyClass();
public int Value { get; set; }
public MyClass() {
this.Value = 10;
}
public override int GetHashCode() {
return Value.GetHashCode();
}
public override bool Equals(Object obj) {
if (obj == this) return true;
var other = obj as MyClass;
return other?.Value == this.Value;
}
}
Now you can check if the instance is equal to a newly created one by calling
if (MyClass.DefaultInstance.Equals(instanceToCheck)) {
... // All defaults
}
You can change what it means for an instance to be "default" by altering DefaultInstance object.
Note: this trick works well only with immutable MyClass. Otherwise some code could perform MyClass.DefaultInstance.Value = 20 and change the "default" object.
Here is one method using JSON serialization that allows you to check if the objects are equal or not:
DotNetFiddle:
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var defaultObj = new MasterObject();
var notDefaultObject = new MasterObject();
var defaultJson = JsonConvert.SerializeObject(defaultObj);
var notDefaultJson = JsonConvert.SerializeObject(notDefaultObject);
Console.WriteLine("First Test");
if (defaultJson == notDefaultJson)
Console.WriteLine("Same thing");
else
Console.WriteLine("Not same thing");
notDefaultObject.Sub1.SomeObject.SomeOtherValue = "Not a default Value";
notDefaultJson = JsonConvert.SerializeObject(notDefaultObject);
Console.WriteLine("Second Test");
if (defaultJson == notDefaultJson)
Console.WriteLine("Same thing");
else
Console.WriteLine("Not same thing");
}
}
public class MasterObject
{
public SubObject1 Sub1 { get; set; }
public SubObject2 Sub2 { get; set; }
public string SomeString { get; set; }
public MasterObject()
{
Sub1 = new SubObject1();
Sub2 = new SubObject2();
SomeString = "Some Default String";
}
}
public class SubObject1
{
public string SomeValue { get; set; }
public SubObject2 SomeObject { get; set; }
public SubObject1()
{
SomeObject = new SubObject2();
SomeValue = "Some other Default String";
}
}
public class SubObject2
{
public string SomeOtherValue { get; set; }
public SubObject2()
{
SomeOtherValue = "Some default";
}
}
Output:
First Test
Same thing
Second Test
Not same thing
What is happening is that you serialize the default object and then you make changes to the "not default object", re-serialize and compare again. This can be slow because you are generating strings, but as long as all the sub-objects can be serialized this will be the simplest way to compare if an object is "default" (what you get from new) or has been modified.

Parameterless Constructor Using ObservableCollection in XAML

I have edited the question. Thanks for the comments below.
It looks like my issue was with a parameterless constructor to declare the class in XAML. However, I can't seem to figure out how to get a parameterless constructor with an observable collection. Please see my code below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace LinkKing.Classes
{
[Serializable()]
public class TheLinks
{
public string linkID;
public string parentID;
public string link;
public DateTime dateAdded;
public int stepAdded;
public string img;
[System.Xml.Serialization.XmlElement("Link")]
public string Link
{
get { return link; }
set { link = value; }
}
[System.Xml.Serialization.XmlElement("DateAdded")]
public DateTime DateAdded
{
get { return dateAdded; }
set { dateAdded = value; }
}
[System.Xml.Serialization.XmlElement("StepAdded")]
public int StepAdded
{
get { return stepAdded; }
set { stepAdded = value; }
}
[System.Xml.Serialization.XmlElement("LinkID")]
public string LinkID
{
get { return linkID; }
set { linkID = value; }
}
[System.Xml.Serialization.XmlElement("ParentID")]
public string ParentID
{
get { return parentID; }
set { parentID = value; }
}
[System.Xml.Serialization.XmlElement("IMG")]
public string IMG
{
get { return img; }
set { img = value; }
}
public TheLinks(string linkID, string parentID, string link, DateTime dateAdded, int stepAdded, string img) : base()
{
this.Link = link;
this.DateAdded = dateAdded;
this.StepAdded = stepAdded;
this.LinkID = linkID;
this.ParentID = parentID;
this.IMG = img;
}
}
public class MyLinks : ObservableCollection<TheLinks>
{
public MyLinks() : base()
{
}
}
}
The error I get is The Type does not include any accessible constructors.
I appreciate everyone's help.
Just based on the code, you have no public parameterless constructor for MyLinks. If you did you would find it on local.
Also usually if it's MVVM, I think having a different namespace for the ViewModel would be better.
Maybe it would also make sense to make your fields (i.e. public string linkID;public string parentID; up to public string img;) private too since you don't access them from outside the class anyway.

Error while implementing IEnumerator

I followed the article here and the sample code given in it.
What I am trying to implement is pretty straightfoward. I do have a fair understanding about collections and enumerators. However, what I don't understand is that even though there is hardly any difference in the way I have implemented the code as compared to how it is implemented in the given article, why I am getting an error.
Only difference in the implementation is that the sample code uses T (generic) whereas I am using a class named Address while implementing the custom Addresses collection class.
The code is pretty straightfoward. I have the following classes in the project.
Contact class
Addresses class (Implements custom collection and inherits from ICollection)
Address class
AddressEnumerator
What I wish to achieve is the Dataset like functionality where we can use a syntax like:
Dataset ds = new Dataset();
Ds.Tables[0]....blah blah blah.
I get a compile time error in the following method of the AddressEnumerator.cs class.
Error:
cannot apply indexing with [] to an expression of type ConsoleApplication2.Addresses (Addresses class implements an ICollection)
Compile time error occurs in the following statement:
_current = _collection[index];
public bool MoveNext()
{
if(++index >= _collection.Count)
{
return false;
}
else
{
_current = _collection[index];
}
return true;
}
Source code:
//following code snippet does not traverse the collection
foreach (Address a in c.Addresses)
{
Console.WriteLine(a.Street);
}
Program.cs
using System;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//RenderTimeSheet();
Address ad = new Address();
ad.Street = "Hollywood";
ad.City = "LA";
ad.State = "California";
ad.ZipCode = "93494";
ad.Country = "USA";
using (Contact c = new Contact(ad))
{
c.FirstName = "John";
c.LastName = "Doe";
Console.WriteLine(c.FirstName);
Console.WriteLine(c.LastName);
foreach (Address a in c.Addresses)
{
Console.WriteLine(a.Street);
}
}
Console.ReadKey();
}
}
Contact.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
namespace ConsoleApplication2
{
public class Contact : IDisposable
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Addresses Addresses { get; set; }
public Contact(Address a)
{
Addresses = new Addresses(a);
}
public Contact()
{
}
public void Dispose()
{
Console.Write("Disposing off...");
}
}
}
Addresses.cs
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
public class Addresses : ICollection<Address>
{
private IList<Address> _lstAddress;
protected bool _IsReadOnly;
public Addresses(Address _a)
{
_lstAddress = new List<Address>();
}
public void Add(Address item)
{
_lstAddress.Add(item);
}
public void Clear()
{
_lstAddress.Clear();
}
public bool Contains(Address item)
{
foreach(Address a in _lstAddress)
{
if(a.Street == item.Street)
{
return true;
}
}
return false;
}
public void CopyTo(Address[] array, int arrayIndex)
{
throw new Exception("Not valid for this implementation.");
}
public int Count
{
get { return _lstAddress.Count; }
}
public bool IsReadOnly
{
get { return _IsReadOnly; }
}
public bool Remove(Address item)
{
bool result = false;
for (int i = 0; i < _lstAddress.Count; i++)
{
Address obj = (Address)_lstAddress[i];
if(obj.Street == item.Street)
{
_lstAddress.RemoveAt(i);
result = true;
break;
}
}
return result;
}
public IEnumerator<Address> GetEnumerator()
{
return new AddressEnumerator(this);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
//throw new NotImplementedException();
return this.GetEnumerator();
}
}
}
Address.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
}
}
AddressEnumerator.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
public class AddressEnumerator : IEnumerator<Address>
{
protected Addresses _collection;
protected int index;
protected Address _current;
public AddressEnumerator()
{
}
public AddressEnumerator(Addresses collection)
{
_collection = collection;
index = -1;
_current = default(Address);
}
public Address Current
{
get
{
return _current;
}
}
public void Dispose()
{
_collection = null;
_current = default(Address);
index = -1;
}
object System.Collections.IEnumerator.Current
{
get
{
return _current;
}
}
public bool MoveNext()
{
if(++index >= _collection.Count)
{
return false;
}
else
{
_current = _collection[index];
}
return true;
}
public void Reset()
{
throw new NotImplementedException();
}
}
}
this is a direct and short solution to your problem,
but it is not a "complete clean" solution, also the coding style of the complete implementation should be changed. there are more effective ways implementing enumerable interfaces ...
change the line
_current = _collection[index];
to
_current = _collection._lstAddress[index];
but you also need to change the access modifier
private IList<Address> _lstAddress
for example to
internal IList<Address> _lstAddress
The reason that the sample code works and yours doesn't is because the sample code class BusinessObjectCollection includes this:
public virtual T this[int index]
{
get
{
return (T)_innerArray[index];
}
set
{
_innerArray[index] = value;
}
}
which provides the subscript operator [] that your code lacks.
If you add that to your Addresses class (changing _innerArray to _lstAddress) then it should work, I think.

C# Code is inaccessible due to its protection level, but all CTORS are Public [duplicate]

This question already has answers here:
What are the default access modifiers in C#?
(10 answers)
Closed 7 years ago.
Learning C# professionally now, and this is a homework program. I can't figure out why one of the three class libraries works without issue, but I can't call any of the other three at all when they where constructed identically to each other.
There are no errors at all in any of the 4 class libraries. All of the Constructors are Public. I have checked the fields, properties, and CTORS multiple times, and none seem to have any issues they are all identical to the student.cs file in every way that I can find, but I can't call them from my console app like I could with student.cs.
The errors I get seem to indicate that the constructors are not public, but they are. I have added the class libraries as a reference to the console all, and included the using statement. Is there anything more that I need to use these other class libraries class files?
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ClassesLibrary; //adding our Class Library to this runnable program
namespace TesterProgram
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***************** Students ******************");
Student s1 = new Student();
s1.FirstName = "David";
s1.LastName = "Castle";
s1.ID = "987";
s1.GPA = 3.87f;
Student s2 = new Student("Michael", "Angelo", "789", 2.8f);
Console.WriteLine(s1);
Console.WriteLine(s2);
Console.WriteLine("******************* Vehicle ******************");
Vehicle v1 = new Vehicle();
v1.Make = "Chevy";
v1.Model = "Malibu";
v1.Year = 2005;
v1.Weight = 2050;
Vehicle v2 = new Vehicle("Ford", "Taurus", 2014, 3000);
Console.WriteLine(v1);
Console.WriteLine(v2);
Console.WriteLine("******************* Login ******************");
Login l1 = new Login();
l1.UserName = "Shaun";
l1.Password = "Forest";
Login l2 = new Login("Alex", "Swing");
Console.WriteLine(l1);
Console.WriteLine(l2);
Console.WriteLine("******************* Contact Info ******************");
ContactInfo c1 = new ContactInfo();
c1.StreetAddress = "112 SW XXXXXXXXXXXXXX Dr.";
c1.City = "XXXX XXXXXXX";
c1.State = "YYYYYYYY";
c1.Zip = "#####";
c1.Phone = "816-XXX-YYYY";
c1.Email = "YYYYY.XXXXXXX#gmail.com";
ContactInfo c2 = new ContactInfo("12418 YYYYY St.", "YYYYYYYYYY YYYY", "YYYYYYY", "#####", "913-XXX-YYYY", "XXXXXXXX#yahoo.com");
Console.WriteLine(c1);
Console.WriteLine(c2);
}
}
}
Student.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassesLibrary
{
public class Student
{
#region Fields
//x TODO fields
private string _firstName;
private string _lastName;
private string _id;
private float _gpa;
#endregion
#region Properties
//x TODO Properties
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}//ends FirstName
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}//ends LastName
public string ID
{
get { return _id; }
set { _id = value; }
}//ends ID
public float GPA
{
get { return _gpa; }
set { _gpa = value; }
}//ends GPA
#endregion
#region CTORS
//x TODO CTORs
//default ctor
public Student() { }
//FQCTOR
public Student(string firstName, string lastName, string id, float gpa)
{
FirstName = firstName;
LastName = lastName;
ID = id;
GPA = gpa;
}
#endregion
#region Methods
//x TODO Methods
public override string ToString()
{
//return base.ToString();
return string.Format("Congratulations {0} {1}, Student ID Number {2}, you have a GPA of {3}",
FirstName,
LastName,
ID,
GPA);
}
#endregion
}//ends class
}//ends namespace
Vehicle.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassesLibrary
{
class Vehicle
{
#region Fields
//x TODO fields
private string _make;
private string _model;
private int _year;
private float _weight;
#endregion
#region Properties
//x TODO Properties
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int Year
{
get { return _year; }
set { _year = value; }
}
public float Weight
{
get { return _weight; }
set { _weight = value; }
}
#endregion
#region CTORs
//x TODO CTORs
//default ctor
public Vehicle() { }
//FQCTOR
public Vehicle(string make, string model, int year, float weight)
{
Make = make;
Model = model;
Year = year;
Weight = weight;
}
#endregion
#region Methods
//x TODO Methods
public override string ToString()
{
//return base.ToString();
return string.Format("I really like your {0} {1} {2}. Are you sure it weighs {3}lbs?",
Year,
Make,
Model,
Weight);
}
#endregion
}//ends class
}//ends namespace
Login.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassesLibrary
{
class Login
{
#region Fields
//x TODO fields
private string _userName;
private string _password;
#endregion
#region Properties
//x TODO Properties
public string UserName
{
get { return _userName; }
set { _userName = value; }
}//ends UserName
public string Password
{
get { return _password; }
set { _password = value; }
}//ends Password
#endregion
#region CTORs
//x TODO CTORs
//default ctor
public Login() { }
//FQCTOR
public Login(string userName, string password)
{
UserName = userName;
Password = password;
}
#endregion
#region Methods
//x TODO Methods
public override string ToString()
{
//return base.ToString();
return string.Format("Congratulations your UserName and Password are {0} {1}.",
UserName,
Password);
}
#endregion
}
}
ContactInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassesLibrary
{
class ContactInfo
{
#region Fields
//x TODO fields
private string _streetAddress;
private string _city;
private string _state;
private string _zip;
private string _phone;
private string _email;
private string p1;
private string p2;
#endregion
#region Properties
//x TODO Properties
public string StreetAddress
{
get { return _streetAddress; }
set { _streetAddress = value; }
}//ends StreetAddress
public string City
{
get { return _city; }
set { _city = value; }
}//ends City
public string State
{
get { return _state; }
set { _state = value; }
}//ends State
public string Zip
{
get { return _zip; }
set { _zip = value; }
}//ends Zip
public string Phone
{
get { return _phone; }
set { _phone = value; }
}//Ends Phone
public string Email
{
get { return _email; }
set { _email = value; }
}//Ends Email
#endregion
#region CTORs
//x TODO CTORs
//default ctor
public ContactInfo() { }
//FQCTOR
public ContactInfo(string streetAddress, string city, string state, string zip, string phone, string email)
{
StreetAddress = streetAddress;
City = city;
State = state;
Zip = zip;
Phone = phone;
Email = email;
}
public ContactInfo(string p1, string p2)
{
// TODO: Complete member initialization
this.p1 = p1;
this.p2 = p2;
}
#endregion
#region Methods
//x TODO Methods
public override string ToString()
{
//return base.ToString();
return string.Format("{0}\n{1}, {2} {3}\n\nPhone: {4}\tEmail: {5}",
StreetAddress,
City,
State,
Zip,
Phone,
Email);
}
#endregion
}
}
Classes are internal by default. So if Vehicle is in a separate assembly you won't be able to access it. Declare the class as public.
public class Vehicle
The constructors are public but the classes in your code are not (classes are internal unless specified otherwise), which means the constructors are only public for calls made from within the same assembly. Make the classes public and their public members will then be accessible to external assemblies.
class Vehicle
is the same as:
internal class Vehicle
The constructors are public, but they forgot to make the class as a whole public.
public class Vehicle
public class Login
public class ContactInfo

Categories

Resources