2013-05-03 33 views
10

Może to pytanie jest głupie, ale w mojej konkretnej sytuacji chcę uzyskać nazwę instancji, więc o co mi chodzi:Uzyskaj nazwę instancji C#

class Student 
{ 
    private string name {get; private set;} 

    public Student(string name) 
    { 
     this.name = name 
    } 

    public getInstanceName() 
    { 
     //some function 
    } 

} 

Więc kiedy zrobić student

Student myStudent = new Student("John"); 

, że to głupie, ale chcę to

myStudent.getInstanceName(); // it should return 'myStudent' 
+1

Więc chcesz nazwę zmiennej? –

+3

Po co tego chcesz? to nie ma sensu. –

+0

Czy chcesz nazwę zmiennej e..g 'myStudent' lub nazwę ucznia, np. 'John'? – eandersson

Odpowiedz

9

nie jest to możliwe w języku C#. W czasie wykonywania nazwy zmiennych nawet nie istnieją, ponieważ JIT usuwa informacje o symbolach.

Ponadto zmienna jest odniesieniem do instancji klasy - wiele zmiennych może odwoływać się do tej samej instancji, a do instancji można odwoływać się za pomocą zmiennych o różnych nazwach w całym okresie istnienia.

1

Nie, nie jest to możliwe, ponieważ jest to całkowicie niedorzeczne. Obiekt nigdy nie może w żaden sposób znać nazwy zmiennej, do której ją przypisałeś. Wyobraź sobie:

Student myStudent = new Student("John"); 
Student anotherStudent = myStudent; 
Console.Write(anotherStudent.getInstanceName()); 

należy powiedzieć myStudent lub anotherStudent? Oczywiście, nie ma pojęcia. Lub zabawniejsze sytuacje:

School mySchool = new School("Harvard"); 
mySchool.enroll(new Student("John")); 
Console.Write(mySchool.students[0].getInstanceName()); 

Naprawdę chciałbym wiedzieć, co to wydrukować.

+2

To nie jest tak absurdalne. Wszystkie te problemy można uzgodnić, zakładając, że zwracana wartość powinna być nazwą zmiennej lub identyfikatora używanego do dereferencji obiektu i wywołania metody. Możliwe jest już uzyskanie numeru linii kodu wywołującego, nazwy metody wywołania itp. Doceniam to, że nie jest to możliwe w CLR ze względu na sposób, w jaki symbole są zarządzane jako stany @Reed Copsey, ale nie jest to śmieszne. Mogę odpowiedzieć na twoje pytanie: "studenci [0]"! –

3

spróbuj tego

string result = Check(() => myStudent); 

static string Check<T>(Expression<Func<T>> expr) 
{ 
    var body = ((MemberExpression)expr.Body); 
    return body.Member.Name; 
} 

Albo

GetName(new { myStudent }); 

static string GetName<T>(T item) where T : class 
{ 
    return typeof(T).GetProperties()[0].Name; 
} 
+2

+1 ode mnie - To interesujące podejście. Zwróć uwagę, że tak naprawdę nie pobiera nazwy zmiennej, tak jak tworzenie nowego typu ze zmienną, która pasuje do niego w polu lub właściwości, i pobieranie tego. Działa w większości przypadków (możesz przerwać to, ale ogólnie rzecz biorąc, ciekawe podejście). –

1

Nazwy zmiennych istnieją tylko dla twojej korzyści podczas kodowania. Po skompilowaniu kodu nazwa myStudent już nie istnieje. Możesz śledzić nazwy instancji w słowniku, jak to:

var students = new Dictionary<string, Student>(); 
var students["myStudent"] = new Student("John"); 

// Find key of first student named John 
var key = students.First(x => x.Value.Name == "John").Key; // "myStudent" 
1

Nie, ale można to zrobić

var myStudent = new Student("John").Named("myStudent"); 
var nameOfInstance = myStudent.Name(); 

public static class ObjectExtensions 
{ 
    private static Dictionary<object,string> namedInstances = new Dictionary<object, string>(); 

    public static T Named<T>(this T obj, string named) 
    { 
     if (namedInstances.ContainsKey(obj)) namedInstances[obj] = named; 
     else namedInstances.Add(obj, named); 
     return obj; 
    } 

    public static string Name<T>(this T obj) 
    { 
     if (namedInstances.ContainsKey(obj)) return namedInstances[obj]; 
     return obj.GetType().Name; 
    } 
} 
13

Jest to obecnie możliwe w C# 6.0:

Student myStudent = new Student("John"); 
var name = nameof(myStudent); // Returns "myStudent" 

ten jest użyteczne w przypadku umów kodu i rejestrowania błędów, ponieważ oznacza to, że jeśli użyjesz "myStudent" w swoim komunikacie o błędzie, a później zdecydujesz się zmienić nazwę "myStudent", będziesz zmuszony przez kompilator do zmiany nazwy wm eessage, a nie zapominać o tym.

+1

FYI C# 6.0! = .net 4.6, więc 'Jest to teraz możliwe z C# 6.0'. Wersja C#, której używasz, jest oparta na obsłudze kompilatora => IDE. Aby napisać w C# 6.0 potrzebujesz Visual Studio 2015. – Athafoud

+0

@Aafeta dzięki za poprawkę :) – elexis

4

To pytanie jest bardzo stare, ale odpowiedź zmieniła się wraz z wydaniem .Net Framework 4.6. Istnieje teraz operator nameof(..), który może być użyty do uzyskania wartości ciągu nazw zmiennych w czasie kompilacji.

Więc do pierwotnego pytania C# nameof(myStudent) // returns "myStudent"