Diskuze: class
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 39 zpráv z 39.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Nejspíš bys udělal struct s privátním konstruktorem a implicitní konverzí z právě třeba toho stringu.
Když použiješ (System.)String tak je stejné jako string. Je to vlastně alias (mám to od <a href="http://stackoverflow.com/questions/7074/whats-the-difference-between-string-and-string">tuď</a>). To definice třídy String je vcelku jasná. Říká že z třídy String nejde dědit a implementuje rozhraní IComparable, ICloneable, IConvertible, IComparable<String>, IEnumerable<char>, IEnumerable, IEquatable<String>. Všechno to je popsaný ve zdejším OOP tutoriálu.
že String == string chápu na to stačí i F12..
jinak už to začínám chápat:
pro inicializaci stačí přepsat implicit operator, jak píše czubehead, něco
jako:
public static implicit operator MyClass(String s)
takže ještě přijít jak na to to:
public static implicit operator MyClass(MyClass s)
zkrátka aby šlo pak udělat toto:
MyClass a;
MyClass b = a;
bez toho abych předával pouze odkaz, ale bylo to klonování třídy
public static MyClass operator = (MyClass x);
už mi nejde dit, tak kecám. Tento operátor nejde přetížit. Nevím sice
proč, ale je to tak.
https://msdn.microsoft.com/…bkb459w.aspx
Nicméně tam píšo něco o implicitním přetypování, třeba to
pomůže.
jde ale pouze takto:
public static implicit operator MyClass(String x);
public static implicit operator MyClass(int x);
public static implicit operator MyClass(bool x);
...
ale takto to nejde:
public static implicit operator MyClass(MyClass x);
hlásí to chybu:
User-defined operator cannot take an object of the enclosing type and convert to
an object of the enclosing type
zatím jsem nenašel řešení
To co chceš se dělá v c# tak, že naimplementuješ IClonable a pak voláš Copy
var a = new A();
var copyOfA = (A)a.Copy();
Implementace metody Copy můžeš dělat několika způsoby:
Pozn. u klonování se tady používají dva termíny a to DeepCopy a
ShallowCopy. Oba mají nějaké rozdíly, tak si když tak dohledej jaký je
mezi nimi rozdíl, já jdu na oběd Určitě je to v dokumentaci někde uvedené u příkladu užití
MemberwiseCopy.
to já vím, IClonable chápu a používám.
Já to na co se ptám, zatím nepotřebuju. Ale už mě kolikrát napadlo, že
při vytvoření kopie stringu se .Copy() nedává. A nenapadá mě proč.
U deep copy se dělají i kopie všech objektů. U shallow copy je jenom zkopírují odkazy.
Jo, už to vidím. Tohle je napsané už v kompilátoru (nemám to podložené), ale je to jen prostě zjednodušení zápisu, abys nemusel psát:
string s = new string(new char[] { 'a', 'b', 'c' });
tak můžeš napsat
string s = "abc";
Zdroj beru intuici, protože podobný způsob je použit např. u delegátů.
Jestli jsem Tě správně pochopil, tak si myslíš, že takhle funguje kompilátor (string je speciální součást kompilátoru), a podobně fungující třída se klasickým způsobem nedá vytvořit (takže tím nemá cenu ztrácet čas).
http://tipsandtricks.runicsoft.com/…utables.html
http://stackoverflow.com/…utable-class
Tohle by ti mělo pomoct. V principu si udržuješ vnitřní stav, tak jak je, aby se nemohl měnit. Tak funguje i string.
Dá se vytvořit, jen prostě vytváření instance bude o pár znaků delší.
Ve skutečnosti je to všechno trochu jinak. Pokud do instance stringu přiřadíš jinej string, tak se string nebude klonovat, ale zkopíruješ jen referenci, jako u každé jiné třídy.
nemyslím si.
Vyzkoušej si to:
class Program
{
static void Main(string[] args)
{
string s1 = "1111";
string s2 = s1;
s2 = "2222";
Console.WriteLine(s1);
Console.WriteLine(s2);
//změnou s2 se s1 nezmění
Console.ReadKey();
}
}
Tady jde pouze o předání reference:
class Program
{
static void Main(string[] args)
{
StringBuilder s1 = new StringBuilder("1111");
StringBuilder s2 = s1;
s2[0] = '+';
Console.WriteLine(s1);
Console.WriteLine(s2);
//zde se změnou s2 změní i s1
Console.ReadKey();
}
}
Teoreticky jo, prakticky je to úplně jedno, protože je string immutable.
Ne, tam pak změníš referenci, takže se logicky první nezmění a druhej bude odkazovat na novou referenci
Ale můžeš novou instanci třídy (pokud není statická), vytvořit pouze pomocí new ne jen pomocí operátoru =, jako u stringu
string a = "----";
string b = a;
Ne, tady tam ukládáš jen referenci
Jde to ověřit takhle:
string a = "abc";
string b = a;
Console.WriteLine(Object.ReferenceEquals(a, b)); //true
Nevyvrátil, nebo nechápu, kam tím míříš
Ve skutečnosti je to všechno trochu jinak. Pokud do instance stringu přiřadíš jinej string, tak se string nebude klonovat, ale zkopíruješ jen referenci, jako u každé jiné třídy.
Ne, tam pak změníš referenci, takže se logicky první nezmění a druhej bude odkazovat na novou referenci
No to je sice pravda, ale proč bych si měl něco vyvracet? Nechápu co jsem
si měl čím vyvrátit
"se string nebude klonovat, ale zkopíruješ jen
referenci"
"tam pak změníš referenci, takže se logicky první nezmění a
druhej bude odkazovat na novou referenci"
připadá Ti to stejné tvrzení?
Ale ono se to taky vztahuje k něčemu jinýmu.
Tady zkopíruješ odkaz (referenci) a obě proměnné tak odkazují na stejnej kus paměti:
string a = "abc";
string b = a;
Tady ale změníš v druhém stringu referenci a tak bude odkazovat na něco jinýho:
string a = "abc";
string b = a; //Zatím stejná reference jako a
b = "cba" //A teď už je jiná, ale a zůstává stejný, protože je to jinej objekt alokovanej jinde
Tady máš ještě jeden důkaz:
class Program
{
static void Main(string[] args)
{
string s = "ssss";
string n = "Ssss";
SetText(ref s, n);
Console.WriteLine(s);
Console.WriteLine(n);
Console.ReadKey();
}
static void SetText(ref string s, string new_s)
{
s = new_s;
new_s = "0000000";
}
}
Klasickou můžeš změnit přes parametr, aniž bys tam dal ref
class Program
{
static void Main(string[] args)
{
TestClass s = new TestClass("ssss");
TestClass n = new TestClass("Ssss");
SetText(ref s, n);
Console.WriteLine(s.txt);
Console.WriteLine(n.txt);
Console.ReadKey();
}
static void SetText(ref TestClass s, TestClass new_s)
{
s.txt = new_s.txt;
new_s.txt = "0000000";
}
}
class TestClass
{
public string txt;
public TestClass(string t)
{
txt = t;
}
}
Důkaz čeho? Tady nejde o nic jinýho než že string je immutable a
string a = "a";
je jen syntaktickej cukr pro
String a = new String("a");
spíš se tady řeší tohle:
String a = new String(String);
jinak, tady máš ještě jeden kód:
class Program
{
static void Main(string[] args)
{
string s = "ssss";
string n = s;
Console.WriteLine(GetPointer(ref s));
Console.WriteLine(GetPointer(ref n));
Console.ReadKey();
}
static long GetPointer(ref string s)
{
IntPtr p = Marshal.StringToCoTaskMemUni(s);
return p.ToInt64();
}
}
Nějak mi uniká pointa o čem se tu bavíte.
jt.e Máš tušení co dělá ten tvůj poslední kód? Resp. co si myslíš, že má dělat.
Nějak mi uniká pointa o čem se tu bavíte.
Mě se prostě nezdá toto tvrzení:
Pokud do instance stringu přiřadíš jinej string, tak se string nebude klonovat, ale zkopíruješ jen referenci, jako u každé jiné třídy.
Vše co ti stačí o stringu vědět je to, kde začíná. To je opravdu vše, co ti stačí vědět. Asi tě napadá, jak teda víš, kde ten string končí. Každý string končí nultým znakem ('\0').
Takže, aby ses nedostal někde mimo do paměti, kde nemáš (neměl bys, uvidíš na příkladě, že můžeš mít) přístup, tak si C# uchovává ještě jak velký ten string je. Obě tyto hodnoty se nastavují v dobe inicializace instance a jakákoliv změna stringu vede k zahození staré instance a vytvoření nové.
Každopádně i C# něco dovolí, tak si můžeš upravit jednotlivé znaky na stringu a vše je naprosto safe.
string str = "abc";
unsafe
{
fixed (char* p = str)
{
Console.WriteLine(p[0]); // a
p[0] = 'x';
Console.WriteLine(p[0]); // x
Console.WriteLine(p[1]); // b
Console.WriteLine(p[2]); // c
Console.WriteLine(p[3]); // 0
}
}
Console.WriteLine(str); // xbc
Dá se udělat v c# pointer na String?
Ano.
Pokud do instance stringu přiřadíš jinej string, tak se string nebude klonovat, ale zkopíruješ jen referenci, jako u každé jiné třídy.
Snad stačí kousek kódu jako ukázka, že se fakt kopíruje jen reference. Je to normální třída.
string str = "abc";
string str2 = str;
unsafe
{
fixed (char* p = str)
{
p[0] = 'x';
}
}
Console.WriteLine(str); // xbc
Console.WriteLine(str2); // xbc
takže Jakub Šárník měl pravdu Omlouvám se, že jsem
nevěřil.
Zobrazeno 39 zpráv z 39.