[OOP] Defining Classes Part One - Задача 4


1
Add a method in the GSM class for displaying all information about it. Try to override ToString().
Изавинявам се за тъпия въпрос, но как успяхте да зададете изписването на цената.? Аз искам да е в евро. Пробвах да добавям в StringBuilder със String.Format("C", и currentCulture) или да добавям само знака '€', но не стана. Знам че бях гледала, но избщо не успявам да намеря.
Благодаря предварително!

в C# OOP от el_b_k (424 точки)


Отговори



1
Console.WriteLine(string.Format(new System.Globalization.CultureInfo("eu"), "{0:C}", price));
Ако на конзолата евро-знакът не ти се показва, това е недостатък на самия терминал който не поддържа знаци извън ascii - опитай да запишеш във файл и ще видиш че си излиза.

от staafl (5770 точки)


0
Много благодаря. Стана в комбинация с Console.OutputEncoding = System.Text.Encoding.UTF8; в началото :)

от el_b_k (424 точки)


1
Пробвай:
string.Format(new CultureInfo("en-US"), "{0:C}", price);
или
price.ToString("C", new CultureInfo("en-US")



0
Супер, това е посоката. Ама еврото не става :( Пробвах с "fr-BE" уж трябва да го изкара а седи ? ...

от el_b_k (424 точки)

0
Добави в началото на кода: Console.OutputEncoding = System.Text.Encoding.UTF8;



1
За всички чудещи се относно последната част от условието:
http://msdn.microsoft.com/en-us/library/ms173154%28v=vs.80%29.aspx
Аз използвам списък, който записвам в StringBuilder, макар че може само StringBuilder, но първо това ми дойде наум.

от vanina_nenova (327 точки)


0
Имам следния въпорс. Като напиша инстанция в класа GSM
public Battery battery = new Battery(); мога да досътпва пропъртитата му. И с ToString() да изпринтирам на конзолата. Обаче като задам някакви стойности от Main() който не е нито в един от 3те класа, защо после не мога да ги порчета от ToString()
Пример: Battery battery = new Battery(5.5, 2.0); в Main()
задавам стойности 5.5 часа в stand-by и 2 часа talk time
после като изпринтя пропъртитата battery.HoursTalk battery.HoursIdle принтя само нули.
Явно че принтирам само default-натите им стойности. Как да направя, че да достъпя зададените от Main :?

от plamentsokov (105 точки)


0
Дай кода да видим какво си пропуснал.

от SVGN_H (3048 точки)

0
Липсва ти конструктор с Battery и Display. В момента те са добавени като fields в класа GSM, но просто си стоят там и никаква роля не играят.
public GSM(string phoneManufacturer, string phoneModel, int phonePrice, string phoneOwner, Battery battery, Display display) { this.model = phoneModel; this.manufacturer = phoneManufacturer; this.price = phonePrice; this.owner = phoneOwner; this.Battery = battery; this.Display = display; }
И в main метода:
gsm.Battery = battery; gsm.Display = display;

от SVGN_H (3048 точки)



0

https://github.com/luzterin/OOP/tree/master/1.DefineClasses/04.OverrideToString

Дали не се оплитам някъде.. Още от началото съм ползвал пропъртита, а гледам следващата задача, че ги изисква..




0
Направи по един override на ToString() и в класовете Дисплей и Батерия, направо там си им прибави атрибутите и само ги извикай в ToString() на GSM-a по името на инстанцията им.
Добре си ползвал пропъртита, но ги използвай и в конструкторите, примерно тук public Display() { this.Size = null; this.NumColors = null; } Контрукторите е добре да ги направиш с наследяване,за да избегнеш повтаряне на код, като по късите наследяват по-дългите, замествайки в наследените с null за полетата който не се въвеждат public Display() : this(null, null) {
}
public Display(double? size) : this(null, size) {
} , докато стигнеш до пълния конструктор в който задаваш стойностите

от el_b_k (424 точки)


5

Колеги искам само да споделя, че е хувато override ToString()  да се направи със StringBuilder, т.к. ще направи програмата да работи по-бързо....ето и конкретната част от моя код:
//OVERRIDE TO STRING()
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder(); //use stringbuilder in order program to operate faster
            sb.Append("Model: " + model);
            sb.Append("\nManufacturer: " + manufacturer);
            if (price != null)
            {
                sb.Append("\nPrice: " + price);
            }
            else
            {
                sb.Append("\nPrice: " + "NA");
            }

            sb.Append("\nOwner: " + owner);
            sb.Append("\nDispay size: " + displayChar.size);
            sb.Append("\nDispay number of colors: " + displayChar.numberOfColors);
            sb.Append("\nBatery hours idle: " + bateryChar.hoursIdle);
            sb.Append("\nBatery hours talk: " + bateryChar.hoursTalk);
            sb.Append("\nBatery model: " + bateryChar.model);
            sb.Append("\nBatery type: " + bateryChar.typeOfBatery);
            string testStr = sb.ToString();
            return testStr;
        }


от zhelyazkovn (2949 точки)


0
Колега Желязков, отлична реализация.Една препоръка- "displayChar.size" и другите полета от външните два класа няма да са достъпни ако са прайвит,т.е. ще трябва да ги замените със свойства,въпреки че свойствата са в следваща задача. Един вид за коректността за цялата задача.+1 от мен.

от RumenTonev (336 точки)

0
Приемам препоръката Ви, колега Тонев, за основателна и изключително полезна. Благодаря Ви!

от zhelyazkovn (2949 точки)



2

Здравейте,

Ето го моето решение за "ToString" метода (тук). Намирам всички публични нестатични свойства и ги ги изпечатвам във формат: name: value.

Решавам задачата така за да избегна въвеждането им "на ръка" в ToString. Друго предимство е, че промяна(добавяне/премахване) на свойствата на класа няма да доведе до промяна на ToString, и че практически съшият код е преизпозлван за другите класове.

Малко пояснения:

I.   Ето я статията за GetProperrties метода в MSDN.

    1. Важно е да се зададе BindingFlags.Instance или BindingFlags.Static заедно с поне още един Binding Flag, иначе методът няма да върне нищо.

    2. В обясненията пише, че НЕ ТРЯБВА ДА СЕ РАЗЧИТА НА РЕДА НА ВЪРНАТИТЕ СВОЙСТВА ЗАЩОТО ТОЙ ВАРИРА. Изпробвах това и не можах да получа варираща подредба(тук). Същност излезе, че последователността ЗАВИСИ от реда на деклариране на свойствата. Ако някой знае или се сети при какви обстоятелства може да се получи различен ред на свойствата - ще се радвам ако каже.

II. Отделил съм създаването на "StringBuider" - а в отделен метод AppendPropertiesNamesAndValues, който изглежда малко по-различно(но незначително), защото ми се струва по-прегледно и защото отделям AppendPropertiesNamesAndValues в отделен клас и го преизползвам за всички останали класове (така измислих да избягвам повторяемост на код - не знам дали е най-добрият вариант).

 


от Stefanpu (404 точки)


0

Искам да попитам следното: Направих и аз String Builder и го кръстих Info. Ще дам пример със GSM.cs и Battery.cs не мога да append-на нищо от другите classove въпреки, че са private. Ето ги и двата:
http://pastebin.com/ny0c49Aj GSM.cs
http://pastebin.com/PGbUt84g Display.cs

Искам да взема стойностите на 

 

private string dispSize;
private int? dispNumOfCols;
и да ги append-на, но не става.

от d3adly (97 точки)


0
GetPhoneInfo() можеш да го изтриеш. ТоString, който си override-нал върши същата работа. Моят съвет е да направиш по един override на ToString във всичките си класове (Battery, Display... ). Добави инстанции на класовете Battery и Display като полета в класа GSM (и още по добре пропъртита към тях, отново в GSM). В оverride на ТоString в StringBuildera добави полетата battery и display (през пропъртитата им) и те ще извикат техните си компоненти от техния си ТоString. В Main-a създай обект от тип GSM и го отпечатай на конзолата. Би трябвало да изпише всичката информация за него, включително и всичката информация за батерията и дисплея му.

от el_b_k (424 точки)


1

Ето едно много кратко и просто решение с Reflection. Взимат се всички свойства с = this.GetType().GetProperties();. И после се прибавят с име и стойност към StringBuilder-а с: AppendLine(propery.Name +":"+ propery.GetValue(this))

Видео за Reflection на Ивайло Кенов: http://www.youtube.com/watch?v=7aXurMWeAa4&feature=youtu.be

 

public override string ToString()
        {
            var result = new StringBuilder();

            var properties = this.GetType().GetProperties();

            foreach (var propery in properties)
            {
                result.AppendLine(propery.Name +":"+ propery.GetValue(this));
            }
                    
            return result.ToString();
        }


от nadetto (125 точки)


0
EDIT:
Браво колежке : ) Аз изгледах лекцията и съм много доволен от видяното/наученото в нея. Наистина с Reflection става много интелигентно. Единственото, което искам да добавя за тези, които тепърва ще ти ползват кода е, че този ред result.AppendLine(propery.Name +":"+ propery.GetValue(this)); след this трябва да включва и null като втори параметър или иначе казано да изглежда така: result.AppendLine(propery.Name +":"+ propery.GetValue(this, null));

от p.penchev (204 точки)


0

Да се включа и аз в темата : )

Това http://pastebin.com/pPBHqNsm са задачите от първа до пета в едно. Ако някой има време ще се радвам да разгледа и да каже това ли се очаква след преминаването от условие в условие.

 

EDIT: http://pastebin.com/NEiVxaZV


от p.penchev (204 точки)


0
Хубаво е да си направиш class-овете в отделни файлове. Също така можеш да използваш автоматични пропъртита т.е. вместо да пишеш: public string Model { get { return model; } set { model = value; } } Може да напишеш: public string Model { get; set; } Също така можеш да си изнесеш Battery newBattery = new Battery("Li-Ion 3100 mAh", 980, 35, BatteryType.LiIon); Display newDisplay = new Display(5.55, 16000000); във втория конструктор т.е. там където имаш model и manufacturer и да махнеш първия, защото в условието на задача 2 се казва, че задължително за създаването на инстанция трябва да въведеш model и manufacturer. Надявам се да съм бил полезен.


0
Благодаря за коментарите, колега : ) Пропъртитата умишлено ги направих така, а класовете ги написах в един файл, за да мога лесно да постна целия код. За празния и единичния конструктор си прав - изтрих ги.

от p.penchev (204 точки)



0

Здравейте, значи като извикам овъррайднатия метод ToString() ми хвърля NullReferenceException. Ето и съобщението: "An unhandled exception of type 'System.NullReferenceException' occurred in MobilePhone.exe

Additional information: Object reference not set to an instance of an object."

Ето и кода вътре в метода, като стигне до 5 -тия ред гърми.

sb.Append("Model: " + model);
sb.Append("\nManufacturer: " + manifacturer);
sb.Append("\nPrice: " + price);
sb.Append("\nlOwner: " + owner);
sb.Append("\nlBattery model: " + battery.Model);
sb.Append("\nlBattery hours iddle" + battery.HoursIdle);
sb.Append("\nlBattery talk hours" + battery.TalkHours);
sb.Append("\nlDisplay size: " + display.Size.ToString());
sb.Append("\nlDisplay colors: " + display.NumberOfColors.ToString());
 
Къде ми е грешката?
 
Edit:
Class GSM - http://pastebin.com/wvxp98B3
Class Battery - http://pastebin.com/Ce9JH4CK
Class Display - http://pastebin.com/qf7mc6cR
Понеже не знам как се поства в сайтове като Github използам Pastebin.
 
Едит: Проблема е решен.

от memo_pu (62 точки)


0
гърми на battery.Model, така ли? Имаш ли getter? Създал ли си обект на battery?
Може ли да качиш целия код на всичките класове някъде? други неща, които трябва да оправиш: 1. трябва да използваш this.model , this.manufacturer и т.н. 2. има sb.AppendLine(string)

от lithical (0 точки)

0
Здравей , мисля че грешката ти е че обектите Battery или Display са ти null в случая, и на мен ми се получи снощи същото. Направи if(this.battery != null ) Sb.Append(battery.Model...) , и if(this.display != null) Sb.Append(display.Size...). Мисля че така няма да гърми,макар че незнам до каква степен е правилно...

от h_stefanov (5 точки)