Здравствуйте, AndrewVK, Вы писали:
VD>>Вот нарыл как можно: VD>>var scoreRecordsDict = scoreRecords.ToDictionary(sr => sr.Name);
AVK>А как это работает? Рефлекшен?
По идее, можно и без рефлекшена:
using System;
using System.Collections.Generic;
public delegate R Func<A,R> (A arg);
public static class Extensions
{
public static Dictionary<K,T> ToDictionary<T,K>(this IEnumerable<T> collection, Func<T,K> func)
{
var dict = new Dictionary<K,T>();
foreach (T elem in collection)
dict.Add(func(elem), elem);
return dict;
}
}
public static class Program
{
public static void Main(string[] args)
{
var dict = (new [] {"aaa", "b", "cccc", "dd"}).ToDictionary(s => s.Length);
Console.WriteLine(dict[3]);
}
}
Здравствуйте, Igor Trofimov, Вы писали:
iT>Перекомпиляция пройдет без ошибок, но скомпилится с "родным" методом String.Split вместо старого StringExt.Split. iT>И будет работать по-другому.
IMHO Так это в принципе нормально. Обратный ход, когда объект работает с одним методом, а пользователь с другим методом — по моему хуже. Аргументацию, примерно вижу такой:
1. Клиент может и не представлять, что некоторый namespace переопределяет данный метод. А следовательно, если он использует эту функциональность в совершенно других целях, то это должен быть родной метод. Если он использует синтаксис extension, то он вполне должен представлять что это синтаксический сахар. Просто удобство вызова методов связанных(не родных) с объектом. То есть, никакого обмана.
2. Можно явно вызвать метод extension, но вызвать переопределенный метод объекта нельзя. Тут уже более криминально, поскольку непонятно как можно определить синтаксис вызова родного объекта. А в связи с п.1, то вообще источник ошибок.
Ну например:
static class TestExtensions
{
public static string ToString(this string str){return"Переопределено";}
}
static void Main(string[] args)
{
string sss="sss";
Console.WriteLine(TestExtensions.ToString(sss));//явно вызываем метод расширения
Console.WriteLine(sss.ToString()); //тут вызов родного метода
}
выдаст
Переопределено
sss
Вообще, один способ держать метод с именем существующего это безусловно интерфейсы.
public interface IMyObject
{
String MyMethod();
}
public class MyObject:IMyObject
{
String IMyObject.MyMethod()
{
return"Real My Method";
}
}
static class TestExtensions
{
public static String MyMethod(this MyObject myObject){return"Extension";}
}
class Program
{
static void Main(string[] args)
{
MyObject obj=new MyObject();
Console.WriteLine(obj.MyMethod());
IMyObject iface=new MyObject();
Console.WriteLine(iface.MyMethod());
}
}
выдает
Extension
My Real Method
Мне непонятно другое. Вот разделить статик метод и this — проблемы
public class MyObject
{
static public string MyMethod()
{
return"My Static Method";
}
}
static class TestExtensions
{
public static String MyMethod(this MyObject myObject){return"Extension";}
}
class Program
{
static void Main(string[] args)
{
MyObject obj=new MyObject();
Console.WriteLine(obj.MyMethod());//Error Static member
//'LINQConsoleApplication1.MyObject.MyMethod()' cannot be accessed
//with an instance reference; qualify it with a type name instead
Console.WriteLine(MyObject.MyMethod());
}
}
Или то же самое но с помощью модификаторов доступа.
public class MyObject
{
private string MyMethod()
{
return"My Static Method";
}
}
static class TestExtensions
{
public static String MyMethod(this MyObject myObject){return"Extension";}
}
class Program
{
static void Main(string[] args)
{
MyObject obj=new MyObject();
Console.WriteLine(obj.MyMethod());//Error Static member
//'LINQConsoleApplication1.MyObject.MyMethod()' cannot be accessed
//with an instance reference; qualify it with a type name instead
Console.WriteLine(MyObject.MyMethod());
}
}
В саму спецификацию, все это вписывается(если не выдавать ошибку сразу, а дойти до конца поиска с генерацией расширений, и уже если не найден "корректный" метод генерить ошибку компиляции).
Но возможно виноват пункт 3
3. Код работающий за пределами расширяемого класса, должен корректно работать в самом классе. Действительно, если мы при рефакторинге перенесем процедуру(код процедуры) в класс, разрешим namespace, совсем не факт что она заработает как она работала до этого. Скорее всего, это и есть реальная причина.
Ну и последнее, это из спецификации(там это написано красным, чтобы было видно):
Extension methods are less discoverable and more limited in functionality than instance methods. For those reasons, it is recommended that extension methods be used sparingly and only in situations where instance methods are not feasible or possible.
Здравствуйте, _FRED_, Вы писали:
_FR>А зачем они делегат Func (из System.Query) назвали сокращённо? Есть же прекрасное слово Function _FR>Надеюсь, поправят
Поправляю. Судя по всему ты не любишь Visual Basic. Там уже давно забили это слово под себя.
Здравствуйте, TK, Вы писали:
>> А зачем они делегат Func (из System.Query) назвали сокращённо? >> Есть же прекрасное слово Function
TK>А еще есть прекрасное слово "анонимный делегат". А то, понапридумывали TK>каких-то стрелочек...
До этого, если не ошибаюсь, в именах типов не встречались сокращения (не путать с аббревиатурами).
Давай тогда и IsolatedStorageFileStream преобразуем в IsltStrgFileStrm
Здравствуйте, GlebZ, Вы писали:
_FR>>А зачем они делегат Func (из System.Query) назвали сокращённо? Есть же прекрасное слово Function _FR>>Надеюсь, поправят GZ>Поправляю. Судя по всему ты не любишь Visual Basic. Там уже давно забили это слово под себя.
Здравствуйте, VladD2, Вы писали:
_FR>>А зачем они делегат Func (из System.Query) назвали сокращённо? Есть же прекрасное слово Function _FR>>Надеюсь, поправят
VD>Это еще что. А вон зачем было запихивать делегаты общего назначения в пространство имен System.Query?
Я даже сперва подумал, что лямбды ни во что, кроме Func<x, ...> преобразовываться не умеют
Да и давно уже пора пользоваться CommonGenericsLibrary