2015-04-06 2 views
4

Я смотрел на this question, и это заставило меня задуматься.Перегружатели недвижимости

Всякий раз, когда я определить класс с авто свойствами,

// Example A 
public class MyObject 
{ 
    public int MyInt { get; set; } 
} 

ЛТ-компилятор преобразует его в похожее на это:

// Example B 
public class MyObject 
{ 
    private int _MyInt; 

    public int get_MyInt() 
    { 
    return _MyInt; 
    } 

    public void set_MyInt(int value) 
    { 
    _MyInt = value; 
    } 
} 

Таким образом, вы могли бы гипотетически написать что-то вроде следующего:

// Example C.1 
public class MyObject 
{ 
    public int MyInt { get; set; } 

    public void set_MyInt(string value) 
    { 
    MyInt = int.Parse(value); 
    } 
} 

Возможно, что-то такое:

// Example C.2 
public class MyObject 
{ 
    private int _myInt; 
    public int MyInt 
    { 
    get { return _myInt; } 
    set 
    { 
     _myInt = value; 
    } 
    set(string) 
    { 
     _myInt = int.Parse(value); 
    } 
    } 
} 

И эта функциональность существует без ошибок компилятора.

// Example D 
public void DoSomething(string someIntegerAsAString) 
{ 
    var myObject = new MyObject() 
    { 
    MyInt = someIntegerAsAString 
    }; 
} 

Что останавливает компилятор от высказывания код, такой как примере D, где желаемый результат выведенного и он работает правильно и ожидалось? Функциональность там, указанная в Пример B.

Это что-то противоречит тому, как языковые дизайнеры разработали язык для работы и поведения?

+0

Ничто не останавливает вас в первом примере. Ошибки компиляции останавливают вас во втором. Перегруженные средства настройки свойств не поддерживаются. Вы могли бы просто использовать метод. Вероятно, есть некоторые экзотические способы злоупотреблять им, поэтому зачем тратить время, усилия и деньги на что-то очень редко? –

+0

На самом деле вы можете выполнять перегрузку метода с помощью динамических привязок http://www.hanselman.com/blog/BackToBasicsC4MethodOverloadingAndDynamicTypes.aspx, невозможно с помощью свойства auto-IMPLEMENTED, но иногда это может помочь – Random

+0

Возможный дубликат [Перегрузка свойств в C#] (https://stackoverflow.com/questions/2608892/overloading-properties-in-c-sharp) – DavidRR

ответ

0

Вы можете, конечно, сделать это ...

public class MyObject 
{ 
    public int MyInt { get; set; } 

    public void set_MyInt(string value) 
    { 
    MyInt = int.Parse(value); 
    } 
} 

... несмотря на очевидную производительность накладных расходов преобразования строки в междунар.

Это не будет работать:

public class MyObject 
{ 
    private int _myInt; 
    public int MyInt 
    { 
    get { return _myInt; } 
    set 
    { 
     _myInt = value; 
    } 
    set(string) 
    { 
     _myInt = int.Parse(value); 
    } 
    } 
} 

... потому, что C# не поддерживает setter перегрузки. Тем не менее, вы можете достичь чего-то подобного с implicit type conversion, но он должен быть реализован на ваших собственных типах. Integer - это тип значения, поэтому он по сути запечатан.

+0

Я это понимаю. Но * key *, о котором я говорю, заключается в том, что компилятор распознает эту функциональность. На мой взгляд, я хочу получить дополнительную информацию (на высоком уровне) о том, почему компилятор не поддерживает что-то вроде этого, где, с моей точки зрения, существует базовая инфраструктура для функциональности. – Cameron

+1

@Cameron: Я понимаю, что я очень опаздываю на вечеринку, но, будучи постоянным читателем блога Эрика Липперта (который работал на компиляторе C#), я считаю, что наиболее вероятным объяснением того, почему компилятор C# не разрешает перегруженные сеттеры, является следующее: Это просто не воспринималось как полезная или достаточно важная языковая функция. Как всегда говорил Эрик, реализация функции имеет стоимость, поэтому, если функция не нужна достаточно плохо, ее там не будет. – stakx

0

Дизайнеры C# дали нам возможность реализовать неявное преобразование типа. Однако они, вероятно, не хотели, чтобы это работало с примитивными типами, чтобы избежать путаницы.

Представьте эти строки:

var myvar = 2; 
myvar = "4"; 

Каждый ищет в строках выше будет думать, что мы говорим о динамическом языке, как JavaScript. В JavaScript myvar будет строкой из второй строки. Если C# поддерживает то, что вы описали, оно все равно будет int. Я, например, сочтет это запутанным.

1

Это не JIT, который генерирует методы get_* и set_*.

Если вы декомпилировать этот код:

public int MyInt { get; set; } 

вы получите этот IL:

.property instance int32 MyInt() 
{ 
    .get instance int32 C::get_MyInt() 
    .set instance void C::set_MyInt(int32) 
} // end of property C::MyInt 

.method public hidebysig specialname instance int32 
     get_MyInt() cil managed 
{ 
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (01 00 00 00) 
    // Code size  11 (0xb) 
    .maxstack 1 
    .locals init (int32 V_0) 
    IL_0000: ldarg.0 
    IL_0001: ldfld  int32 C::'<MyInt>k__BackingField' 
    IL_0006: stloc.0 
    IL_0007: br.s  IL_0009 
    IL_0009: ldloc.0 
    IL_000a: ret 
} // end of method C::get_MyInt 

.method public hidebysig specialname instance void 
     set_MyInt(int32 'value') cil managed 
{ 
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (01 00 00 00) 
    // Code size  8 (0x8) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: ldarg.1 
    IL_0002: stfld  int32 C::'<MyInt>k__BackingField' 
    IL_0007: ret 
} // end of method C::set_MyInt 

Если вы посмотрите на PropertyInfo, вы увидите, что она имеет GetMethod и SetMethod. «Метод», а не «Методы».

Это связано с каркасом, хотя я не знаю ни одного языка, на котором свойство имеет более одного геттера или сеттера. Вы знаете какой-либо такой язык?

+0

LinqPad показывает упрощенный вид IL. Я думаю, что результат ildasm был бы более полезен здесь. – svick

+0

Каким образом, @svick? –

+0

Потому что он отобразит '.property' и установит там геттер и сеттер. – svick

Смежные вопросы