Почему при неявной реализации метода интерфейса нельзя возвращать из метода более производный тип, чем указано в интерфейсе? Приходится писать явную реализацию интерфейса плюс дополнительный публичный метод, возвращающий нужный тип. Не знаете ли, исправится ли ситуация с добавлением контравариантности в C# 4.0?
Здравствуйте, Аноним, Вы писали:
А>Почему при неявной реализации метода интерфейса нельзя возвращать из метода более производный тип, чем указано в интерфейсе? Приходится писать явную реализацию интерфейса плюс дополнительный публичный метод, возвращающий нужный тип.
я делаю наоборот — пишу публичный метод с производным типом, а в явной реализации дергаю его.
А>Не знаете ли, исправится ли ситуация с добавлением контравариантности в C# 4.0?
Здравствуйте, Ovl, Вы писали:
Ovl>nikov должен знать. по моему — да
Думаю, что не изменится, потому что компилятор будет использовать возможности, уже существующие в CLR, а сейчас такое сделать с помощью Reflection.Emit не получается. К тому же, Ecma-335 содержит такой текст:
The method signature defined by MethodBody shall match those defined by MethodDeclaration.
Сигнатура (грубо говоря, тип) возвращаемого значения является частью сигнатуры метода. Правда, мне не удалось найти определение термина match для сигнатур, но думаю, он означает точное совпадение всех составляющих.
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, Ovl, Вы писали:
Ovl>>nikov должен знать. по моему — да
N>Думаю, что не изменится, потому что компилятор будет использовать возможности, уже существующие в CLR, а сейчас такое сделать с помощью Reflection.Emit не получается. К тому же, Ecma-335 содержит такой текст:
N>
N>The method signature defined by MethodBody shall match those defined by MethodDeclaration.
N>Сигнатура (грубо говоря, тип) возвращаемого значения является частью сигнатуры метода. Правда, мне не удалось найти определение термина match для сигнатур, но думаю, он означает точное совпадение всех составляющих.
странно, что они так сделали, потому что в с++ например возвращаемое значение не входит в сигнатуру..
другими словами, CS0111 по-моему некоторое насилие поверх overloading-ом.
этому были нормальные объяснения? выполняется все же в рантайме ведь, да и язык ссылочный. не думаю, что включение типа возврата в сигнатуру было обосновано.
Здравствуйте, Ovl, Вы писали:
Ovl>другими словами, CS0111 по-моему некоторое насилие поверх overloading-ом. Ovl>этому были нормальные объяснения? выполняется все же в рантайме ведь, да и язык ссылочный. не думаю, что включение типа возврата в сигнатуру было обосновано.
Это в CLR так. В C# возвращаемое значение не входит в сигнатуру метода, а в CLR — входит.
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, Ovl, Вы писали:
Ovl>>другими словами, CS0111 по-моему некоторое насилие поверх overloading-ом. Ovl>>этому были нормальные объяснения? выполняется все же в рантайме ведь, да и язык ссылочный. не думаю, что включение типа возврата в сигнатуру было обосновано.
N>Это в CLR так. В C# возвращаемое значение не входит в сигнатуру метода, а в CLR — входит.
ну если есть предположения по вопросу — буду рад услышать
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, Ovl, Вы писали:
Ovl>>ну если есть предположения по вопросу — буду рад услышать
N>Ну значит я не понял вопрос. Объясни подробнее.
Сделать через емит можно многое
Правда не все можно оставить для потомства, то есть сделать AssemblyBuilder.Save
class Program
{
const string typeName = "MyHelloWorld";
const string methodName = "MyHelloWorld";
const MethodAttributes methodAttrs = MethodAttributes.Public | MethodAttributes.Virtual;
readonly static Type[] methodParams = new Type[] { typeof(string) };
static void Dump(IEnumerable<MethodInfo> miList)
{
foreach (MethodInfo mi in miList)
Console.Out.WriteLine(mi.Name);
}
static void Main()
{
Type main = CreateDynamic();
Dump(main.GetMethods());
CallHelloWorld(main);
}
private static void CallHelloWorld(Type main)
{
try
{
main.InvokeMember(methodName,
BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, Type.DefaultBinder,
Activator.CreateInstance(main), new object[] { "Aga!" });
}
catch (Exception e)
{
Console.Error.WriteLine(">>> " + e.Message);
}
}
static Type CreateDynamic()
{
AssemblyName myAssemblyName = new AssemblyName();
myAssemblyName.Name = "Example";
// Create the callee dynamic assembly.
AssemblyBuilder myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
myAssemblyName, AssemblyBuilderAccess.RunAndSave);
// Create a dynamic module in the callee assembly.
ModuleBuilder myModule = myAssembly.DefineDynamicModule("EmittedModule");
// Define a public class named "MyHelloWorld".
TypeBuilder myHelloWorldType =
myModule.DefineType(typeName, TypeAttributes.Public);
MethodBuilder myHelloMethod = myHelloWorldType.DefineMethod(
methodName, methodAttrs, typeof(string), methodParams);
MethodBuilder myHelloMethod2 = myHelloWorldType.DefineMethod(
methodName, methodAttrs, typeof(void), methodParams);
GenerateBody(myHelloMethod);
GenerateBody(myHelloMethod2);
return myHelloWorldType.CreateType();
}
private static void GenerateBody(MethodBuilder mi)
{
ILGenerator myMethodIL = mi.GetILGenerator();
myMethodIL.Emit(OpCodes.Ldstr, "Hi! ");
myMethodIL.Emit(OpCodes.Ldarg_1);
MethodInfo infoMethod =
typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
myMethodIL.Emit(OpCodes.Call, infoMethod);
myMethodIL.Emit(OpCodes.Ret);
}
}
Я имел ввиду — зачем все же в CLR это могло понадобиться? Почему обязательно нужно было включать возвращаемое значение в сигнатуру?
Здравствуйте, Ovl, Вы писали:
Ovl>Я имел ввиду — зачем все же в CLR это могло понадобиться? Почему обязательно нужно было включать возвращаемое значение в сигнатуру?
Приведенный тобой код поднимает более узкий вопрос: почему CLR позволяет перегружать методы по возвращаемому значению?
Ну хотя бы для того, чтобы можно было представить в виде методов user-defined conversions (op_Explicit, op_Implicit). Вообще, CLR и IL стараются накладывать минимум ограничений — мало ли какие возможности понадобятся в других языках.
А понятие сигнатуры используется для многих целей в Ecma-335 (не только для перегрузки). Для них важно учитывать и возвращаемое значение.
Здравствуйте, nikov, Вы писали:
N>Думаю, что не изменится, потому что компилятор будет использовать возможности, уже существующие в CLR, а сейчас такое сделать с помощью Reflection.Emit не получается. К тому же, Ecma-335 содержит такой текст:
Ну учитывая следующий CLR (в смысле 4.0), то все возможно
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"