Why doesn't the ", Second ID: " string in O.W2() get printed out? I know that the D2 property is empty.
using System;
public class O
{
public string F { get; set; }
public string L { get; set; }
public string D { get; set; }
public virtual string W()
{
return this.W2();
}
public virtual string W2()
{
return string.Format("First Name : {0}, Last name: {1}, ID: {2}", F, L, D);
}
}
public class S : O
{
public string D2 { get; set; }
public override string W()
{
return base.W2();
}
public override string W2()
{
return base.W2() + string.Format(", Second ID: {0}", this.D2);
}
}
class Program
{
static void Main(string[] args)
{
O o = new S();
o.D = "12345678";
o.F = "John";
o.L = "Jones";
Console.WriteLine(o.W());
// Output: First Name : John, Last name: Jones, ID: 12345678
}
}
Because you called override W() which in turn calls base.W2(). Inside the class, base.W2() is determined statically (at compile time) to be the one in the base class:
public override string W()
{
// directly calls W2() from the base class, ignores the override
return base.W2();
}
If you want polymorphism for this scenario, you should omit base and just call W2():
public override string W()
{
// goes to the override
return W2();
}
The function W2() in the S object is never called!!
Bec when you called W() in S object u made it call the base W2()
Try like this:
public override string W()
{
String x = base.W2();
x = x + this.W2();
return x;
}
Related
public void sortByType(){}
what should i enter here if i have three types of customers different in the way they pay
I have a class customer that inhereted 3 other classes they have a name ,id ,balance and a name of the books array and the date of barrowing and returning how can i sort them by
types??
class Book
{
public string BName { get;set; }
public string Day { get;set; }
public string Month { get;set;} }
public string Year { get;set;} }
public override string ToString(){}
}
then I created an abstract class Customer
abstract class Customer
{
protected string name;
protected double balance;
protected double ID_num;
protected Book[] rental_books = new Book[3];
public string Name { get { return name; } set { name = value; } }
public double Balance { get { return balance; } set { balance = value; } }
public double ID_NUM { get { return ID_num; } set { ID_num = value; } }
public override string ToString() {}
public abstract void BarrowBook(string bn, string d, string m, string y);
public abstract void ReturnBook(string bn, string d, string m, string y);
public abstract void AddToBalance(double sum);
}
and inherted it to the other three child classes and add what I need to each method
class NormalCustomer : Customer{}
class MemberCustomer : Customer{}
class StudentCustomer : Customer{}
then I created a library class
class Library
{
private Customer[] customers;
private int MaxCust=0;
private int count = 0;
public Library(int MaxCust) { this.MaxCust = MaxCust; }
public void Add(Customer c) { customers[count++] = c; }
public void ToString() {
public void SortByBalance()
{
double hold;
for (int i = 0; i < customers.Length - 1; i++)
for (int k = 0; k < (customers.Length - 1) - i; k++)
{
if (customers[k].Balance > customers[k + 1].Balance)
{
hold = customers[k].Balance;
customers[k].Balance = customers[k + 1].Balance;
customers[k + 1].Balance = hold;
}
}
}
}
so all i need now is the methode i mentioned above and how to creat it
let's take your classes
public class Customer { ... }
public class NormalCustomer : Customer{}
public class MemberCustomer : Customer{}
public class StudentCustomer : Customer{}
Providing an array which contains all the children in a mixed order:
Customer [] array = new Customer[]
{
new StudentCustomer(),
new MemberCustomer(),
new NormalCustomer(),
new MemberCustomer(),
new StudentCustomer(),
new StudentCustomer(),
new NormalCustomer(),
};
You can use the method: OfType to extract the individual types:
var children_1 = array.OfType<NormalCustomer>();
var children_2 = array.OfType<MemberCustomer>();
var children_3 = array.OfType<StudentCustomer>();
Now you simply need to concatenate them into a single collection using the Concat method. It expects that the second collection contains the same type of elements so you need to cast it temporarily to the parent type:
Customer [] sorted children_1.Cast<Customer>().Concat(children_2).Concat(children_3).ToArray();
I have a class with two variables: Name, Address
I instantiate the class, add values to it, and try to store it in a list. Once I do that I hope to print the Name and Adress on the console but I'm not sure what I'm doing wrong:
public class Test
{
public string Name { set; get; }
public string Address { set; get; }
}
static void Main(string[] args)
{
Test t = new Test();
t.Name = "bob";
t.Address = "CT";
List<Test> lst = new List<Test>();
lst.Add(t);
foreach (var x in lst)
{
Console.WriteLine(x);
}
}
WHen I do this I simply get the name of my project.ClassName
Simply, override ToString and everything else should work as you'd expect it to.
Example:
class Test
{
public string Name { set; get; }
public string Address { set; get; }
public override string ToString(){
return $"name: {Name}, address: {Address}";
}
}
You can utilize the ToString in your class. When passed your class-instance to the Console.WriteLine function, this ToString-function is called.
For further information check the documentation for Console.WriteLine and object.ToString().
public class Test
{
public string Name { set; get; }
public string Address { set; get; }
public override string ToString()
{
return $"Name: {Name} Address: {Address}";
}
}
static void Main(string[] args)
{
Test t = new Test();
t.Name = "bob";
t.Address = "CT";
List<Test> lst = new List<Test>();
lst.Add(t);
foreach (var x in lst)
{
Console.WriteLine(x);
}
}
This will output:
Name: bob Address: CT
You need to access the Name property inside for loop
foreach (var x in lst)
{
Console.WriteLine(x.Name);
}
for me i will use this
static void Main(string[] args)
{
Test t = new Test();
t.Name = "bob";
t.Address = "CT";
List<Test> lst = new List<Test>();
lst.Add(t);
lst.ForEach(show);
}
private static void show(Test obj)
{
Console.WriteLine(obj.Name);
Console.WriteLine(obj.Address);
}
If you want to have it print the properties dynamically whenever the class is updated, you can use Json.Net.
class Test
{
public string Name { set; get; }
public string Address { set; get; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
I have following class:
public class ContentVideoType
{
public string Title { get; set; }
public string GetThumbnail { get; set; }
}
When creating an instance of this class, I want to assign a custom getter for GetThumbnail. I don't know how it is called but as far as I know the code must be like:
var youtube = new ContentVideoType
{
Title = "Youtube",
GetThumbnail = (x) => { return $"https://i.ytimg.com/vi/{x}/mqdefault.jpg"; }
};
var vimeo = new ContentVideoType
{
Title = "Vimeo",
GetThumbnail = (x) => GetVimeoImage(x)
};
For Viemo for example I need to call following function for GetThumbnail:
public static string GetVimeoImage(string vimeoId)
{
string result = String.Empty;
try
{
XmlDocument doc = new XmlDocument();
doc.Load("http://vimeo.com/api/v2/video/" + vimeoId + ".xml");
XmlElement root = doc.DocumentElement;
result = root.FirstChild.SelectSingleNode("thumbnail_medium").ChildNodes[0].Value;
}
catch
{
//cat with cheese on it's face fail
}
return result;
}
I suppose, that you want to achieve inheritance in some odd way :) You should really use proper inheritance here (GetThumbnail should be method if it is receiving a string as a parameter):
public abstract class ContentVideoType
{
public virtual string Title { get; set; }
public virtual string GetThumbnail(string id)
{
return "Some Default Thumbnail";
}
}
public class YouTubeContentVideType : ContentVideoType
{
public override string GetThumbnail(string id)
{
return "";//your logic for youTube
}
}
public class VimeoContentVideType : ContentVideoType
{
public override string GetThumbnail(string id)
{
return "";//your logic for vimeo
}
}
=== UPDATE ===
Basing on your latest response - here is how it would look :
void Main()
{
foreach (var videoType in GetAll)
{
Console.WriteLine(videoType.Title + " " + videoType.GetThumbnail("1")));
}
}
public abstract class ContentVideoType
{
public virtual string Title { get; }
public virtual string GetThumbnail(string id)
{
return "Some Default Thumbnail";
}
}
public class YouTubeContentVideoType : ContentVideoType
{
public override string Title { get; } = "Youtube";
public override string GetThumbnail(string id)
{
return $"https://i.ytimg.com/vi/{id}/mqdefault.jpg";
}
}
public class VimeoContentVideType : ContentVideoType
{
public override string Title { get; } = "Vimeo";
public override string GetThumbnail(string id)
{
return GetVimeoPreview(id);
}
public string GetVimeoPreview(string videoId)
{
return $"url:{videoId}"; //your code here;
}
}
public static List<ContentVideoType> GetAll
{
get
{
var result = new List<ContentVideoType>
{
new YouTubeContentVideoType(),
new VimeoContentVideType()
};
return result;
}
}
It sounds like you want GetThumbnail to be a method that returns a string, not just a string. You can re-declare this way in order to do that:
public Func<string, string> GetThumbnail { get; set; }
That would cause this code to compile:
var youtube = new ContentVideoType
{
Title = "Youtube",
GetThumbnail = (x) => {
return string.Format("https://i.ytimg.com/vi/{0}/mqdefault.jpg", x); }
};
Note that the GetThumbnail above only accepts a method that takes one argument and returns a string.
Edit: Here's an example of how to use this:
string thumbnail = youtube.GetThumbnail("abc");
Could you create two sub-classes to ContentVideoType and each one implementing their own version of GetThumbnail?
Otherwise, the fact of being able to swap getters with reflection seems impossible: https://stackoverflow.com/a/6835824/2525304
Ok, here is how I did it with a little help and guessing :)
public class ContentVideoType
{
public string Title { get; set; }
public Func<string, string> GetThumbnail { get; set; }
}
public static List<ContentVideoType> GetAll
{
get
{
var result = new List<ContentVideoType> {
new ContentVideoType
{
Title = "Youtube",
GetThumbnail = videoId => $"https://i.ytimg.com/vi/{videoId}/mqdefault.jpg"
},
new ContentVideoType
{
Title = "Vimeo",
GetThumbnail = videoId => GetVimeoPreview(videoId)
}
};
return result;
}
}
I want that a.ID() returns 0 and b.ID() returns 1 and here is my code:
public class A {
public static int id;
public int ID() {return id;}
}
public class B : A { }
public class Main {
void Program() { //This executes when I execute the program
A.id = 0;
B.id = 1;
}
}
But it doesn't work, this also doesn't work:
public class A {
public static int id;
public int ID() {return id;}
}
public class B : A {
public new static int id; //id is actually 1 but ID() is still 0
}
public class Main {
void Program() { //This executes when I execute the program
A.id = 0;
B.id = 1;
}
}
How can I fix this?
You can create two static variables and one virtual property
public class A
{
private static int _idA;
public virtual int Id
{
get { return _idA; }
set { _idA = value; }
}
}
public class B : A
{
private static int _idB;
public override int Id
{
get { return _idB; }
set { _idB = value; }
}
}
Or one property and use new keyword to override it
public class A
{
public static int Id { get; set; }
}
public class B : A
{
public static new int Id { get; set; }
}
To test first solution you can try following
static void Main(string[] args)
{
A test = new B();
new B().Id = 3;
new A().Id = 2;
test.Id = 1;
Console.WriteLine(test.Id + " " + new B().Id + " " + new A().Id);
Console.ReadKey();
}
If you can accept these rules:
The numbers can be anything, ie. any legal int
They don't have to start at 0
They don't have go up by 1 for each new unique type
The numbers are allowed to change between executions of your program
ie. you run your program and type A returns id 33554436
You change the program (somewhere else) and rerun, now type A returns id 33554437 (a different value)
then here is a way to get your ID:
public class Base
{
public int ID
{
get
{
return GetType().MetadataToken;
}
}
}
You don't need to override this property to get unique id's for each type but you can no longer guarantee what the values will be, here's example output from two such derived classes:
33554436
33554437
If I added a new type between those two and reran, I got:
33554436
33554438
If you're afraid the constant trip to reflection is going to be expensive here is an alternative declaration:
public class Base
{
private readonly Lazy<int> _ID;
protected Base()
{
_ID = new Lazy<int>(() => GetType().MetadataToken);
}
public int ID
{
get
{
return _ID.Value;
}
}
}
You can make the ID method virtual and override it in the B class like this:
public class A
{
public static int id;
public virtual int ID() { return id; }
}
public class B : A
{
public static int id;
public override int ID()
{
return id;
}
}
Here is another way to do it that uses Reflection:
public class A
{
public static int id;
public int ID()
{
return (int)this.GetType()
.GetField("id", BindingFlags.Static | BindingFlags.Public)
.GetValue(null);
}
}
public class B : A
{
public static int id;
}
This way, you don't have to override the ID method on each subclass. However, you still need to defined a static id field in each subclass.
I am porting some Delphi code to C# on a system where I can read different kind of fields from the same source. I would like to use a parent class and encapsulate all internal way of do on child classes to hide the internal and concrete mechanism of every field type.
I have done a simple example to show where is "my problem":
using System;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
ParentField<int> fieldInteger = new MyIntField<int>();
fieldInteger.Value = 12;
ParentField<string> fieldString = new MyStringField<string>();
fieldString.Value = "This is a String";
Console.WriteLine("1. The Integer Value: " + fieldInteger.Value);
Console.WriteLine("1. The String Value: " + fieldString.Value);
int localInteger = fieldInteger.GetRealStrongTypedValue;
string localString = fieldString.GetRealStrongTypedValue;
Console.WriteLine("2. The Integer Value: " + localInteger);
Console.WriteLine("2. The String Value: " + localString);
}
}
public abstract class ParentField<T>
{
public abstract Object Value { get; set; }
public abstract T GetRealStrongTypedValue { get; }
}
public sealed class MyIntField<T> : ParentField<T>
{
public override Object Value
{
get { return valor; }
set { valor = (int)value; }
}
public override T GetRealStrongTypedValue
{
get { return valor; } // ERROR...
}
private int valor;
}
public sealed class MyStringField<T> : ParentField<T>
{
public override Object Value
{
get { return valor; }
set { valor = (string)value; }
}
public override T GetRealStrongTypedValue
{
get { return valor; } // ERROR...
}
private string valor;
}
}
Also I have tried removing Generic from child GetRealStrongTypedValue instance method, in this way:
public sealed class MyStringField<T> : ParentField<T>
{
public override Object Value
{
get { return valor; }
set { valor = (string)value; }
}
public new string GetRealStrongTypedValue
{
get { return valor; }
}
private string valor;
}
But then the error is I am not implementing abstract method from ParentField Class.
I have tried to change ParentField.GetRealStrongTypedValue to virtual, implementing fake content, but polymorphism doesn't run at all and always is using the exact ParentField.GetRealStrongTypedValue so it is returning fake content.
Any simple and smart idea ? :-)
Thanks...
I think what you want to do is not make MyStringField generic, but rather make it a type-specific implementation of ParentField<T>.
public sealed class MyStringField : ParentField<string>
{
public override Object Value
{
get { return valor; }
set { valor = (string)value; }
}
public override string GetRealStrongTypedValue
{
get { return valor; } // ERROR...
}
private string valor;
}