Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
jt.e
Člen
Avatar
jt.e:10.10.2015 20:32

Zdravím, zajímá mě ještě jedna věc:
Jak vytvořit třídu podobného typu jako je String?
Tedy třídu, která není modifikovatelná, lze ji změnit pouze tak, že se vytvoří nová, lze ji inicializovat jako string: string s = "abc";

Editováno 10.10.2015 20:33
 
Odpovědět
10.10.2015 20:32
Avatar
Petr Čech
Tvůrce
Avatar
Odpovídá na jt.e
Petr Čech:10.10.2015 21:12

Nejspíš bys udělal struct s privátním konstruktorem a implicitní konverzí z právě třeba toho stringu.

Nahoru Odpovědět
10.10.2015 21:12
the cake is a lie
Avatar
jt.e
Člen
Avatar
jt.e:10.10.2015 22:23

strukturu si dokážu představit, ale string je "public sealed class String : IComparable, ICloneable, IConvertible, IComparable<Strin­g>, IEnumerable<char>, IEnumerable, IEquatable<Strin­g>"

 
Nahoru Odpovědět
10.10.2015 22:23
Avatar
Ondřej Štorc
Tvůrce
Avatar
Odpovídá na jt.e
Ondřej Štorc:10.10.2015 22:32

Když použiješ (System.)String tak je stejné jako string. Je to vlastně alias (mám to od <a href="http://­stackoverflow­.com/question­s/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<Strin­g>, IEnumerable<char>, IEnumerable, IEquatable<String>. Všechno to je popsaný ve zdejším OOP tutoriálu.

Nahoru Odpovědět
10.10.2015 22:32
Život je příliš krátký na to, abychom bezpečně odebírali USB z počítače..
Avatar
jt.e
Člen
Avatar
jt.e:10.10.2015 23:31

ž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

 
Nahoru Odpovědět
10.10.2015 23:31
Avatar
Odpovídá na jt.e
Patrik Valkovič:10.10.2015 23:35
public static MyClass operator = (MyClass x);
Editováno 10.10.2015 23:35
Nahoru Odpovědět
10.10.2015 23:35
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Patrik Valkovič:10.10.2015 23:39

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.

Nahoru Odpovědět
10.10.2015 23:39
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
jt.e
Člen
Avatar
Odpovídá na Patrik Valkovič
jt.e:10.10.2015 23:48

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í

 
Nahoru Odpovědět
10.10.2015 23:48
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na jt.e
Jan Vargovský:11.10.2015 12:54

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:

  1. Kopírování 1:1 všech věcí, které chceš zkopírovat
  2. Zavolání MemberwiseCopy() z třídy Object
  3. Projetí reflexí a překopírování jednotlivých věcí
  4. Použít nějaký mapper (třeba AutoMappper, ale nezkoušel jsem)

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 :D Určitě je to v dokumentaci někde uvedené u příkladu užití MemberwiseCopy.

 
Nahoru Odpovědět
11.10.2015 12:54
Avatar
jt.e
Člen
Avatar
Odpovídá na Jan Vargovský
jt.e:11.10.2015 14:02

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č.

 
Nahoru Odpovědět
11.10.2015 14:02
Avatar
Milan Křepelka
Tvůrce
Avatar
Milan Křepelka:11.10.2015 14:07

U deep copy se dělají i kopie všech objektů. U shallow copy je jenom zkopírují odkazy.

 
Nahoru Odpovědět
11.10.2015 14:07
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na jt.e
Jan Vargovský:11.10.2015 15:08

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ů.

Editováno 11.10.2015 15:11
 
Nahoru Odpovědět
11.10.2015 15:08
Avatar
jt.e
Člen
Avatar
Odpovídá na Jan Vargovský
jt.e:11.10.2015 18:14

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).

 
Nahoru Odpovědět
11.10.2015 18:14
Avatar
Odpovídá na jt.e
Patrik Valkovič:11.10.2015 18:19

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.

Nahoru Odpovědět
11.10.2015 18:19
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na jt.e
Jan Vargovský:11.10.2015 18:36

Dá se vytvořit, jen prostě vytváření instance bude o pár znaků delší.

 
Nahoru Odpovědět
11.10.2015 18:36
Avatar
Neaktivní uživatel:11.10.2015 19:58

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.

Nahoru Odpovědět
11.10.2015 19:58
Neaktivní uživatelský účet
Avatar
jt.e
Člen
Avatar
Odpovídá na Neaktivní uživatel
jt.e:11.10.2015 21:35

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();
    }
}
 
Nahoru Odpovědět
11.10.2015 21:35
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
Jan Vargovský:11.10.2015 21:37

Teoreticky jo, prakticky je to úplně jedno, protože je string immutable.

 
Nahoru Odpovědět
11.10.2015 21:37
Avatar
Odpovídá na jt.e
Neaktivní uživatel:11.10.2015 21:38

Ne, tam pak změníš referenci, takže se logicky první nezmění a druhej bude odkazovat na novou referenci

Nahoru Odpovědět
11.10.2015 21:38
Neaktivní uživatelský účet
Avatar
jt.e
Člen
Avatar
Odpovídá na Jan Vargovský
jt.e:11.10.2015 21:42

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;
 
Nahoru Odpovědět
11.10.2015 21:42
Avatar
Odpovídá na jt.e
Neaktivní uživatel:11.10.2015 21:43

Ne, tady tam ukládáš jen referenci :-)

Editováno 11.10.2015 21:44
Nahoru Odpovědět
11.10.2015 21:43
Neaktivní uživatelský účet
Avatar
jt.e
Člen
Avatar
Odpovídá na Neaktivní uživatel
jt.e:11.10.2015 21:44

teď sis vyvrátil, co jsi před tím napsal :)

 
Nahoru Odpovědět
11.10.2015 21:44
Avatar
Neaktivní uživatel:11.10.2015 21:45

Jde to ověřit takhle:

string a = "abc";
string b = a;
Console.WriteLine(Object.ReferenceEquals(a, b)); //true
Nahoru Odpovědět
11.10.2015 21:45
Neaktivní uživatelský účet
Avatar
Odpovídá na jt.e
Neaktivní uživatel:11.10.2015 21:46

Nevyvrátil, nebo nechápu, kam tím míříš

Nahoru Odpovědět
11.10.2015 21:46
Neaktivní uživatelský účet
Avatar
jt.e
Člen
Avatar
Odpovídá na Neaktivní uživatel
jt.e:11.10.2015 21:48

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

 
Nahoru Odpovědět
11.10.2015 21:48
Avatar
jt.e
Člen
Avatar
jt.e:11.10.2015 21:48

string a = "abc";
string b = "abc";
Console.Write­Line(Object.Re­ferenceEquals(a, b)); //true

 
Nahoru Odpovědět
11.10.2015 21:48
Avatar
Odpovídá na jt.e
Neaktivní uživatel:11.10.2015 21:51

No to je sice pravda, ale proč bych si měl něco vyvracet? Nechápu co jsem si měl čím vyvrátit :-D

Nahoru Odpovědět
11.10.2015 21:51
Neaktivní uživatelský účet
Avatar
jt.e
Člen
Avatar
Odpovídá na Neaktivní uživatel
jt.e:11.10.2015 21:54

"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í?

 
Nahoru Odpovědět
11.10.2015 21:54
Avatar
Odpovídá na jt.e
Neaktivní uživatel:11.10.2015 21:58

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
Nahoru Odpovědět
11.10.2015 21:58
Neaktivní uživatelský účet
Avatar
jt.e
Člen
Avatar
Odpovídá na Neaktivní uživatel
jt.e:11.10.2015 21:59

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;
    }
}
 
Nahoru Odpovědět
11.10.2015 21:59
Avatar
Odpovídá na jt.e
Neaktivní uživatel:11.10.2015 22:05

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");
Nahoru Odpovědět
11.10.2015 22:05
Neaktivní uživatelský účet
Avatar
jt.e
Člen
Avatar
Odpovídá na Neaktivní uživatel
jt.e:11.10.2015 22:20

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();
    }
}
 
Nahoru Odpovědět
11.10.2015 22:20
Avatar
Jan Vargovský
Tvůrce
Avatar
Jan Vargovský:11.10.2015 22:23

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.

 
Nahoru Odpovědět
11.10.2015 22:23
Avatar
jt.e
Člen
Avatar
Odpovídá na Jan Vargovský
jt.e:11.10.2015 22:30

Ne ten poslední je blbě, máš pravdu.

 
Nahoru Odpovědět
11.10.2015 22:30
Avatar
jt.e
Člen
Avatar
Odpovídá na Jan Vargovský
jt.e:11.10.2015 22:33

Dá se udělat v c# pointer na String?

 
Nahoru Odpovědět
11.10.2015 22:33
Avatar
jt.e
Člen
Avatar
Odpovídá na Jan Vargovský
jt.e:11.10.2015 22:37

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.

 
Nahoru Odpovědět
11.10.2015 22:37
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na jt.e
Jan Vargovský:11.10.2015 22:47

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
Editováno 11.10.2015 22:49
 
Nahoru Odpovědět
11.10.2015 22:47
Avatar
jt.e
Člen
Avatar
Odpovídá na Jan Vargovský
jt.e:11.10.2015 23:02

takže Jakub Šárník měl pravdu :) Omlouvám se, že jsem nevěřil.

 
Nahoru Odpovědět
11.10.2015 23:02
Avatar
jt.e
Člen
Avatar
jt.e:11.10.2015 23:07

Jdu študovat Immutable typy :)

 
Nahoru Odpovědět
11.10.2015 23:07
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 39 zpráv z 39.