Error with using ToString in ToString override - c#

I am new to coding and I have a problem with using ToString override. When I try to use already overloaded class's ToString in other ToString override, I get this error:
An object reference is required to non static field, method, or property Freight.ToString()
Please help!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TruckCmopany
{
class Truck
{
private string name;
private double weightCapacity;
private List<Freight> freights;
public Truck(string name,double weightCapacity)
{
this.Name = name;
this.WeightCapacity = weightCapacity;
List<Freight> freights = new List<Freight>();
}
public string Name
{
get { return name; }
set { name = value; }
}
public double WeightCapacity
{
get { return weightCapacity; }
set { weightCapacity = value; }
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(this.Name).Append(" - ");
if (freights.Count==0)
{
sb.Append("Nothing loaded");
}
else
{
sb.Append(string.Join(", ", freights)).Append(Freight.ToString());
}
return sb.ToString();
}
public IReadOnlyCollection<Freight> Freights
{
get => freights.AsReadOnly();
}
public void AddFreight(Freight freight)
{
}
}
}

Freight.ToString() is a call to a static method. It confuses the compiler, because it tries to resolve the call to the non-static .ToString inherited from object.
Since static classes cannot override members, if you really need a static ToString in your Freight class, you need to mark the method with new public.
Well, I see that your Freight is not a static class.
Then if I got you right, and you want a comma-separated string of freights, you need to simply do
sb.Append(string.Join(", ", freights));
It will call .ToString for each element implicitly.

To be able to call Freight.ToString() ToString() has to be a static function, i.e., a function that belongs to the class itself that doesn't require any specific instance of the class to get invoked. However when you convert ToString to be static, you won't have access to the this modifier, since in a static method, there is no instance that you can refer to with this. So you are going to have to pass an instance of Freight to your static function.
You can then override ToString() and inside pass this to your static function. If you want to.
Read on Static Members: MSDN
Read on Methods: MSDN

Related

Methods, arguments, and member variables, not accessible in Windows to Mono port

I can't find this addressed on SO. I am porting a Windows .NET application, that compiles and runs perfectly, to Mono on Linux. I have missed something small. Here is a part of the code:
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace DAPTimeClock
{
public static class DatabaseOps
{
private static string _dbFile;
public static string Get_dbFile()
{
return _dbFile;
}
public void Set_dbFile(string value)
{
this._dbFile = value;
}
public static bool foundFile = false;
public static string SetFile(String dblocation = #"Data" +
"Source=../db/TimeClock.db; Version=3;")
{
Set_dbFile( dblocation );
int pathStart = Get_dbFile().IndexOf ('=') + 1;
int pathEnd = Get_dbFile().IndexOf (";") - 1;
string filePath = Get_dbFile().Substring (pathStart,
pathEnd - pathStart + 1);
if (File.Exists (filePath)) {
foundFile = true;
return string.Format ("The db file {0} has been " +
"located", filePath);
} else
{
foundFile = false;
return string.Format("Unable to find db file {0}.",
filePath);
}
}
public static bool AddPerson(Person p)
{
bool result = false;
Class Continues .....
Here are the issues:
Other classes can't find any methods from this class. ex. DatabaseOp.Set_dbFile() Yields no such method.
The methods in this class can't find methods from this class.
The methods in this class can't see the outside classes.
If I pass an argument to the methods in the class, the complier says it can't find a parameter by that name.
The methods in the class can't see its own member variables.
I have done the following:
I removed the static, now making regular objects. (no change)
I double checked the namespaces. (all the same, no typos)
I tried making the member variable public and adding a get; and set;
I am stumped. Can anyone see what might be hanging this up? Is there something about mono I missed? All other classes are working fine.
Set_dbFile should be declared as
public static void Set_dbFile(string value)
compiler should complain: "cannot declare instance members in static class". Have you miss this?

What is the use of "this" in Java and/or C#? [duplicate]

This question already has answers here:
When do you use the "this" keyword? [closed]
(31 answers)
Closed 9 years ago.
Say I have a simple sample console program like below. My question is in regards to this. Is the sole use of this just so you can use the input variable name to assign to the instance variable? I was wondering what the use of this is other than used in the context of this program?
public class SimpleClass {
int numberOfStudents;
public SimpleClass(){
numberOfStudents = 0;
}
public void setStudent(int numberOfStudents){
this.numberOfStudents = numberOfStudents;
}
public void printStudents(){
System.out.println(numberOfStudents);
}
public static void main(String[] args) {
SimpleClass newRandom = new SimpleClass();
newRandom.setStudent(5);
newRandom.printStudents();
}
}
Previously, when I needed to assign a value to an instance variable name that shares similarities to the input value, I had to get creative with my naming scheme (or lack of). For example, the setStudent() method would look like this:
public void setStudent(int numberOfStudentsI){
numberOfStudents = numberOfStudentsI;
}
From that example above, it seems like using this replaces having to do that. Is that its intended use, or am I missing something?
Things are quite the opposite of how you perceive them at the moment: this is such an important and frequently used item in Java/C# that there are many special syntactical rules on where it is allowed to be assumed. These rules result in you actually seeing this written out quite rarely.
However, except for your example, there are many other cases where an explicit this cannot be avoided (Java):
referring to the enclosing instance from an inner class;
explicitly parameterizing a call to a generic method;
passing this as an argument to other methods;
returning this from a method (a regular occurrence with the Builder pattern);
assigning this to a variable;
... and more.
this is also used if you want to a reference to the object itself:
someMethod(this);
There is no alternative to this syntax (pun intended).
It's also used to call co-constructors, and for C# extension methods.
'this' simply refers to the object itself.
When the compilers looks for the value of 'numberOfStudents', it matches the 'closest' variable with this name. In this case the argument of the function.
But if you want to assign it to the class variable, you need to use the 'this.'-notation!
In the method
public void setStudent(int numberOfStudents){
this.numberOfStudents = numberOfStudents;
}
for example.
'this.numberOfStudents' references the class variable with the name 'numberOfStudents'
'numberOfStudents' references the argument of the method
So, this method simple assigns the value of the parameter to the class variable (with the same name).
in c# you use this to refer the current instance of the class object immagine you have class like this from msdn
class Employee
{
private string name;
private string alias;
private decimal salary = 3000.00m;
// Constructor:
public Employee(string name, string alias)
{
// Use this to qualify the fields, name and alias:
this.name = name;
this.alias = alias;
}
// Printing method:
public void printEmployee()
{
Console.WriteLine("Name: {0}\nAlias: {1}", name, alias);
// Passing the object to the CalcTax method by using this:
Console.WriteLine("Taxes: {0:C}", Tax.CalcTax(this));
}
public decimal Salary
{
get { return salary; }
}
}
class Tax
{
public static decimal CalcTax(Employee E)
{
return 0.08m * E.Salary;
}
}
class MainClass
{
static void Main()
{
// Create objects:
Employee E1 = new Employee("Mingda Pan", "mpan");
// Display results:
E1.printEmployee();
}
}
/*
Output:
Name: Mingda Pan
Alias: mpan
Taxes: $240.00
*/
You have different scopes of variables in Java/C#. Take this example below. Although this.numberOfStudents and numberOfStudents have the same name they are not identical.
public void setStudent(int numberOfStudents){
this.numberOfStudents = numberOfStudents;
}
this.numberOfStudents is a variable called numberOfStudents that is in the instance of this class. this always points on the current instance.
public void setStudent(int numberOfStudents) that numberOfStudents is a new variable that is just available in this method.
keyword "this" refers to an object of the current class (SimpleClass) on the fly.
public class SimpleClass(){
private int a;
private int b;
private int c;
public SimpleClass(int a, int b){
this.a = a;
this.b = b;
}
public SimpleClass(int a, int b, int c){
// this constrcutor
this(a,b);
this.c = c;
}
}

Correct missing fields values

I have a class, that should support version tolerant serialization
[Serializable]
class A {
[OptionalField]
int a;
[OptionalField]
MyClass b;
[OptionalField]
MyClass c;
}
How can I correct missing fields after deserialization? I guess, I have to use method marked with [OnDeserializing]. But how can I get which of fields was ignored?
Can I configure auto-deserialization to initialize field by default constructor in case of them missing?
Additionally, you can use OnSerializingAttribute and OnSerializedAttribute to set the fields. As the example shows, fields that have been already set will keep their value. Note, however, that this is only the case if the field is set during the OnSerializing event. Fields set during the OnSerialized event will override the serialized value.
EDIT: In this case you can check in your method (decorated with OnSerialized) if the field equals to null and instantiate when necessary. If there is the possibility that this field is never be used and its creation can be deferred, think about hiding the field in question behind a property and instantiate it lazily.
Models.cs:
using System;
using System.Runtime.Serialization;
namespace SerializationExample
{
[Serializable]
public class Model
{
public Model(){
A = new SomeClass();
}
[OptionalField]
public int value;
[OptionalField]
public SomeClass A;
[OptionalField]
public AnotherClass B;
[OnDeserializing]
void OnDeserializing(StreamingContext context)
{
B = new AnotherClass("Set during deserializing");
}
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
// Do sth. here after the object has been deserialized
}
public override string ToString()
{
return String.Format("A: {0}\nB: {1}", A, B);
}
}
[Serializable]
public class SomeClass
{
public string Value { get; set; }
public SomeClass()
{
Value = "Default";
}
public override string ToString()
{
return Value;
}
}
[Serializable]
public class AnotherClass
{
public string Value { get; private set; }
public AnotherClass(string v)
{
Value = v;
}
public override string ToString()
{
return Value;
}
}
}
Program.cs:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace SerializationExample
{
class Program
{
static void Main(string[] args)
{
string[] FileNames = new string[] {
#"model1.bin",
#"model2.bin"
};
Stream[] files = new Stream[] {
File.Create(FileNames[0]),
File.Create(FileNames[1])
};
BinaryFormatter bf = new BinaryFormatter();
Model m1 = new Model();
m1.B = new AnotherClass("Set in app");
m1.A.Value = "Set in app";
Model m2 = new Model();
Console.WriteLine("M1:\n{0}\n", m1);
Console.WriteLine("M2:\n{0}\n\n", m2);
bf.Serialize(files[0], m1);
bf.Serialize(files[1], m2);
foreach (var f in files)
f.Seek(0, SeekOrigin.Begin);
m1 = null;
m2 = null;
m1 = (Model)bf.Deserialize(files[0]);
m2 = (Model)bf.Deserialize(files[1]);
Console.WriteLine("M1:\n{0}\n", m1);
Console.WriteLine("M2:\n{0}\n\n", m2);
foreach (var f in files)
f.Close();
}
}
}
Output:
M1:
A: Set in app
B: Set in app
M2:
A: Default
B:
M1:
A: Set in app
B: Set in app
M2:
A: Default
B: Set during deserializing
If you just want to initialize those values to defaults, all you need is a default parameterless constructor that initializes them. This will get called during deserialization, and any missing fields will keep whatever values you initialized them to in the constructor.
If you want more control, you can implement the ISerializable interface and the proper constructor on your class (you should usually do both, though often one or the other is unneeded.)
If C# finds a constructor with the signature:
protected A ( SerializationInfo info, StreamingContext context )
{
}
it will call that constructor, and pass a weakly-typed dictionary with all of the serialization information it has. (You can use ISerializable::GetObjectData to write custom fields into the object and retrieve them in the constructor). You can use the info.GetXXX methods to extract those values.
One thing to note: if you implement this constructor, you have to do all of the work, including the fields that would normally get deserialized automatically. For any missing fields, just set them appropriately. Similarly, if you implement GetObjectData, you have to serialize everything in that method. It's pretty simple, but if you change your class you need to edit your custom method/constructor appropriately.

How does Console.WriteLine() know how to convert an object to a string

I am following the Preamble: what is a reference type? where it explains parameters passing as value or reference type. The first example has the following code:
using System;
using System.Text;
public class Example1
{
public static void Main (string[] args)
{
StringBuilder first = new StringBuilder();
StringBuilder second = first;
first.Append ("hello");
first = null;
Console.WriteLine (second);
}
}
And it does not provide the source code for the class (or struct) of StringBuilder, and I do not know how the Console.WriteLine(second) is able to return a string value just by using the identifier. Is it possible to return a value in the constructor?
I tried to write the class or struct by following (and it doesn't work):
struct StringBuilder
{
private string _myString;
public string StringBuilder
{
get { return _myString; }
set { _myString = value; }
}
public void Append(string str)
{
_myString = str;
}
}
Have a look a the documentation for Console.WriteLine(object value). It says this:
the ToString method of value is called to produce its string
representation, and the resulting string is written to the standard
output stream.
So (as others have written), if you want to print a string representation of your own class or struct, you should override the ToString() method.
StringBuilder is .net class in System.Text namespace.
Override ToString method for objects string representation.
public override string ToString()
{
return _myString;
}
Or print out your property:
Console.WriteLine (second.StringBuilder);
StringBuilder is a class, not a struct. C# is not like C++ in this respect: the two are in fact different. And Console.WriteLine(x) where x is an arbitrary class ends up as Console.WriteLine(x.ToString()).
What the code does is to call ToString on the StringBuilder instance. The code gets clearer if you explicitly call ToString instead of letting it be called implicitly:
Console.WriteLine(second.ToString());
You can override the ToString method in your own class. You should use classes, by the way, only use structs if you have a specific need for it. Structs are more complicated to implement correctly.
Example:
class Example {
public string Value { get; set; }
public Example(string value) {
Value = value;
}
public override string ToString() {
return Value;
}
}
Now the string value of your object will be its value:
Example ex = new Example("test");
Console.WriteLine(ex);

C#: Properties with different return types on derived classes

I tried to search for an answer for this problem but could not find much, most probably because I do not know how to look for it properly, so here it goes. All help is very much appreciated.
With the base class that looks like
abstract public class Property
{
private String name;
public Property(String propertyName)
{
name = propertyName;
}
public String Name
{
get { return name; }
}
abstract public override String ToString();
}
And derived classes that look like
public class StringProperty : Property
{
private String value; // different properties for different types
public StringProperty(String propertyName, String value) : base(propertyName)
{
this.value = value;
}
public String Value // different signature for different properties
{
get { return value; }
}
public override String ToString()
{
return base.Name + ": " + value;
}
}
During runtime, the function receives a collection of "Property" objects. What do I need to do to be able to obtain the "Value" of each? Do I need to have a big if statement to query the type of each "Property" object? If not, is there a more elegant solution?
I tried to define an abstract "Value" property to be overridden but since the return types are different, it did not work. I also tried playing with shadowing the "Value" property, but I could not make it work. The idea of using an COM-like Variant does not sound very appropriate, either.
Thanks a lot in advance.
EDIT:
I should have added details as to what I am trying to do. The properties are displayed in a Winforms app. Different "TextBox"es represent different properties and are filtered for proper input (depending on the type). The updated values are read back and stored. The container object will be serialized into JSON and deserialized on an Android and iPhone client and eventually these values will be passed into a layer running native C++ code doing OpenGL stuff. I don't know in advance the kind of all needed properties so as the middleman, I wanted to make my code as robust as possible while being able to feed the OpenGL engine.
You can use a generic class:
public class AnyProperty<T> : Property
{
private T value;
// ... etc
I'd really recommend making the base class an Interface by now:
public interface IProperty
{
public String Name { get; }
}
public class Property<T> : IProperty
{
public Property(String name, T value)
{
Name = name;
Value = value;
}
public String Name { get; private set; }
public T Value { get; private set; }
public override String ToString()
{
return string.Format("{0}: {1}", Name, Value)
}
}
Here is sample usage:
var intProp = new Property<int> ("age", 32);
var strProp = new Property<string> ("name", "Earl");
var enumProp = new Property<ColorEnum> ("eye color", ColorEnum.Magenta);
To make the construction even simpler, you could have a factory method:
public static Property<T> MakeProperty(string name, T value)
{
return new Property<T>(name,value);
}
var intProp = MakeProperty("age", 32);
var strProp = MakeProperty("name", "Earl");
var enumProp = MakeProperty("eye color", ColorEnum.Magenta);
Not necessarily recommended, and a bit OT:
You could make it even funkier with an extension method:
public static Property<T> AsProp<T>(this T value, string name)
{
return new Property<T>(name,value);
}
var intProp = 32.AsProp("age");
var strProp = "Earl".AsProp("name");
var enumProp = ColorEnum.Magenta.AsProp("eye color");
You would have to simply use the object type. What are you trying to accomplish? The problem here isn't the structure of your classes, it's the function that receives the collection of Property objects. It's impossible to even cast something to an unknown type, since you don't know what type of variable it needs to be stored in.
So basically, your Property.Value property needs to be of type object. In your method that uses the Property objects, you need to do something with them, and what you're doing will decide how it should be structured. Are you printing values out? Have a *Value class inheriting from an abstract PropertyValue class and override ToString() to return an appropriate string represention.
I made a few changes to your sample code and got this result...
abstract public class Property
{
private readonly String _name;
public Property(String propertyName)
{
_name = propertyName;
}
public String Name
{
get { return _name; }
}
abstract public override String ToString();
}
public class StringProperty : Property
{
private readonly dynamic _value; // different properties for different types
public StringProperty(String propertyName, dynamic value)
: base(propertyName)
{
this._value = value;
}
public dynamic Value // different signature for different properties
{
get { return _value; }
}
public override String ToString()
{
return base.Name + ": " + _value;
}
}
static void Main(string[] args)
{
StringProperty sp = new StringProperty("A double", 3.444);
StringProperty sp2 = new StringProperty("My int", 4343);
StringProperty sp3 = new StringProperty("My directory", new DirectoryInfo("Some directory"));
StringProperty sp4 = new StringProperty("My null", null);
Console.WriteLine(sp);
Console.WriteLine(sp2);
Console.WriteLine(sp3);
Console.WriteLine(sp4);
}
}
Values are properly printed to the console in the expected way.
It would require a bit of a rethink, but have you considered using the dynamic type (introduced in .net4)
Doesn't really solve your problem, but sidespteps it.
Your properties can bascically just be a
Dictionary<String, dynamic>
, the gotcha is they don't get evaluated until runtime, so you get no compiler support for typing.
so given you want
int SomeValue = MyProperties[SomePropertyName] + 10;
So if
MyProperties[SomePropertyName] = 10; // all is good
if its 76.52 or Fred, the addition will throw an exception at the point it executes.
Code is much simpler and cleaner, no extra casting and the amount of scaffolding required is minimal, BUT, you'll need to unit test code that uses the dictionary extensively and religiously.

Categories