I want to create a wrapper function for a generic class like so:
public class ColumnData
{
public static ColumnData<T> Create<T>(string name, int width, ColumnType type,
Func<T, string> dataFormater)
{
return new ColumnData<T>(name, width, type, dataFormater);
}
}
The Create method will be called as an argument to another function with a signature:
public void populateFromData<TDATA>(IEnumerable<TDATA> data,
params ColumnData<TDATA>[] columns)
{
...
}
The intent here is to be able to do:
var myData = new List<MyDataType>();
dataListView.populateFromData(
myData,
ColumnData.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString());
However, Create can't infer the correct type for itself based on the signature it's expected to have, and thus the lambda doesn't know itself either.
Is this a limitation of type inference, or is there a way to make this setup work?
Note: I'm willing to specify the actual data type somewhere in this function call, if necessary, but I don't want to specify it for each .Create().
As others have explained, it's not possible with the exact syntax you want. As a workaround, you could possibly move the typing to a separate building class:
public class ColumnDataBuilder
{
public static ColumnDataBuilder<T> ColumnsFor<T>(IEnumerable<T> data)
{
return new ColumnDataBuilder<T>(data);
}
}
public class ColumnDataBuilder<T> : ColumnDataBuilder
{
public IEnumerable<T> Data { get; private set; }
public ColumnDataBuilder(IEnumerable<T> data)
{
this.Data = data;
}
public ColumnData<T> Create(string name, int width, ColumnType type, Func<T, string> dataFormater)
{
return new ColumnData<T>(name, width, type, dataFormater);
}
public void populateFromData(params ColumnData<T>[] columns)
{
///...
}
}
public class ColumnData<T>
{
public ColumnData(string name, int width, ColumnType type, Func<T, string> dataFormatter)
{
}
}
Then usage might look like:
var builder = ColumnDataBuilder.ColumnsFor(new List<MyDataType>());
builder.populateFromData(builder.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString()));
IEnumerable<MyDataType> data = builder.Data;
Or closer to your example usage (if you want to keep populateFromData on your dataListView) in which case you can ditch the ColumnDataBuilder<T>.populateFromData method (since it seems from your comments that's not possible to keep there):
var myData = new List<MyDataType>();
var builder = ColumnDataBuilder.ColumnsFor(myData);
dataListView.populateFromData(myData, builder.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString()));
Or a bit of best of both worlds:
var builder = ColumnDataBuilder.ColumnsFor(new List<MyDataType>());
dataListView.populateFromData(builder.Data, builder.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString()));
EDIT: Considering your comments, you probably don't want populateFromData or possibly even the IEnumerable<T> Data stored on the ColumnDataBuilder, so you might simplify to have this instead:
public class ColumnDataBuilder<T> : ColumnDataBuilder
{
public ColumnData<T> Create(string name, int width, ColumnType type, Func<T, string> dataFormater)
{
return new ColumnData<T>(name, width, type, dataFormater);
}
}
public class ColumnDataBuilder
{
public static ColumnDataBuilder<T> ColumnsFor<T>(IEnumerable<T> data)
{
return new ColumnDataBuilder<T>();
}
}
With the usage from above:
var myData = new List<MyDataType>();
var builder = ColumnDataBuilder.ColumnsFor(myData);
dataListView.populateFromData(myData, builder.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString()));
Sometimes you just have to specify the generic type parameter explicitly, when c# cannot infer it's actual type.
dataListView.populateFromData(
myData,
ColumnData.Create<MyDataType>("ID", 40, ColumnType.Numeric, x => x.ID.ToString());
One answer I just came up with involves an alias. I removed the wrapper class and moved the Create method into the ColumnData<T> class directly, then added:
using ColumnData = ColumnData<MyDataType>;
This allows me to access ColumnData.Create() with the type hint to the compiler, without needing to specify it on each line. I'll need to create the alias in each file where I want to use this, but it is a workable solution.
Related
Consider a situation:
I have a method which use DataRow:
public void MyMethod (DataRow input)
{
DoSomething(input["Name1"]);
}
But now I have some another input types with indexer which I want to pass to this method. St like:
public void MyMethod (AnyTypeWithIndexer input)
{
DoSomething(input["Name1"]);
}
But I haven't found anything like that. I tried IDictionary but it didn't work.
Is there any super type st like "Indexable" or anything with which I can replace the "AnyTypeWithIndexer"?
Note: I still need this method to pass the DataRow and also my custom class (which I want to implement).
Can anybody help?
Thanks.
No, unfortunately, there is no interface that automatically applies to "all classes with an indexer that takes a string argument and returns an object".
What you can do, however, is to create a "proxy class" that implements such an interface
yourself:
public interface IStringToObjectIndexable
{
object this[string index] { get; set; }
}
class DataRowWrapper : IStringToObjectIndexable
{
private readonly DataRow row;
public DataRowWrapper(DataRow row) => this.row = row;
public object this[string index]
{
get => row[index];
set => row[index] = value;
}
}
MyMethod can now be declared as follows:
public void MyMethod(IStringToObjectIndexable input)
{
DoSomething(input["Name1"]);
}
// Compatibility overload
public void MyMethod(DataRow input) => MyMethod(new DataRowWrapper(input));
You can use dynamic type, but you will need to be noticed about the disadvantages of dynamic, such as performance drawbacks because of DLR, and the fact that type safety should be on your shoulders
public class WithIndexer
{
public int this[string key] => 42;
}
public static async Task Main()
{
Dictionary<string, int> a = new Dictionary<string, int>();
a.Add("meow", 41);
Foo(a, "meow");
Foo(new WithIndexer(), "key");
}
private static void Foo(dynamic indexed, string key)
{
Console.WriteLine(indexed[key]);
}
Output:
41
42
I have classes which are derived from a base class and would like to instantiate these classes dynamically at run time. Using the following code, I can build a class using the default constructor:
public abstract class Employee : IEmployeeInterface
{
public string Name { get; set; }
public Employee() { }
public Employee(string name)
{
Name = name;
}
}
public static class EmployeeBot
{
static readonly Func<string, Func<Employee>> EmployeeBotFunction = x =>
Expression.Lambda<Func<Employee>>(
Expression.New(Type.GetType(x).GetConstructor(Type.EmptyTypes))
).Compile();
public static Employee InstantiateNewEmployee(string type)
{
string argumentType = string.Format("{1}.{0}", type.ToString(), MethodBase.GetCurrentMethod().DeclaringType.Namespace);
return EmployeeBotFunction(argumentType).Invoke();
}
}
Worker implements Employee and can be created using:
Employee employee = EmployeeBot.InstantiateNewEmployee("Worker");
Then, since Worker has all the same methods as Employee, calling them will give the results from the worker class as expected.
However, I cannot work out how to correctly implement similar code to use a constructor with arguments. For example:
static readonly Func<string, Type[], Func<string, Employee>> NewEmployee = (x, y) =>
Expression.Lambda<Func<string, Employee>>(
Expression.New(Type.GetType(x).GetConstructor(y))
).Compile();
public static Employee InstantiateNewEmployee(string type, string Name)
{
Type[] construct = new Type[] { typeof(string) };
string argumentType = string.Format("{1}.{0}", type.ToString(), MethodBase.GetCurrentMethod().DeclaringType.Namespace);
return NewEmployee(argumentType, construct).Invoke(Name);
}
Calling this method throws an exception:
EmployeesTests.InstantiateEmployeeWithName threw exception:
System.InvalidOperationException: Method may only be called on a Type
for which Type.IsGenericParameter is true.
How can the NewEmployee function be altered to accept the required parameters for the second constructor?
I have answered this with the help of #JSteward so thank you!
Combined with a different version of Expression.New and fixing a stupid mistake I was able to solve this. You cannot instance an abstract class so my constructor should have been on one of the derived classes, e.g public class Worker : Employee and not public abstract class Employee.
The actual error was that the constructor parameter to the Expression.New(Type.GetType(x).GetConstructor(y)); was null because it was not defined on the Worker.
The second example now becomes; (though I'm sure this can be improved!).
static readonly Func<string, Type[], ParameterExpression[], Func<string, Employee>> NewEmployee = (x, y, z) =>
Expression.Lambda<Func<string, Employee>>(
Expression.New(Type.GetType(x).GetConstructor(y), z)
, z).Compile();
public static Employee InstantiateNewEmployee(string type, string Name)
{
Type[] construct = new Type[] { typeof(string) };
string argumentType = string.Format("{1}.{0}", type.ToString(), MethodBase.GetCurrentMethod().DeclaringType.Namespace);
ParameterExpression[] arguments = new ParameterExpression[] { Expression.Parameter(typeof(string)) };
return NewEmployee(argumentType, construct, arguments).Invoke(Name);
}
The post from #JSteward 's comments actually generalises this requirement already: linq-expressions-creating-objects
I appreciate your help and also the comment from the blog.
But good to see that I’m not the only person crazy enough to be using Expressions in this way!
I'm selecting some data from a source and I want to pass this to a generic method for handling the data. Each property I select needs a little bit of meta-data associated for processing. This is roughly what I'd like to be able to do:
var items = from i in db.bar
select new {
a = i.Prop1.ToString(),
b = i.Prop2.ToString(),
c = Prop3
};
// Roughly what I would like to be able to do:
ProcessData(items,
new DataSelector() { Header = "head1", Selector = (d => d.Prop1) },
new DataSelector() { Header = "head2", Selector = (d => d.Prop2) });
The closest I can get is the following:
private class DataSelector<T> {
public string Header { get; set; }
public Func<T, string> Selector { get; set; }
}
private static void Process<T>(IEnumerable<T> stuff,
params ColumnDef<T>[] defs) {
foreach (var item in stuff) {
// Use all defs like...
Console.WriteLine(defs[0].Header + ": " + defs[0].Selector(item));
}
}
Process(items,
new DataSelector<dynamic>() { Header = "head1", Selector = (d => d.Prop1) });
But this allows me to write (d => d.NonExistantProp) and it will compile and fail at runtime (boo, hiss). I can also do it for a single property and maintain type safety because the type seems to be worked out implicitly, but that won't let me pass sets of parameters:
private static void Process<T>(IEnumerable<T> stuff,
string header,
Func<T, string> selector) {
// stuff happens
}
Process(items, "head1", (d => d.Prop1));
So... Is there a way to maintain compile-time type safety of the selector along with groups of related data?
Footnote: I appreciate I could have Process<T>(IEnumerable<T> items, List<string> headers, params Func<T, string> selectors[]) but that also produces run-time errors if the headers don't pair up to the selectors.
What you need is some way of creating a DataSelector that uses type inference based on a given sequence (or item, or anything else that uses the type).
We can create a non-generic DataSelector counterpart that can have a static Create method that can be written in such a way as to allow type inference:
private class DataSelector
{
public static DataSelector<T> Create<T>(IEnumerable<T> sequence,
string header, Func<T, string> selector)
{
return new DataSelector<T>() { Header = header, Selector = selector };
}
}
Now the caller can write:
Process(items, DataSelector.Create(items, "first", item => item.Prop1));
And we are now inferring the type of T for the data selector and don't need to specify a type that has no name.
Note that we're not actually iterating the sequence in this Create method; it's not used at all; it's basically a dummy parameter.
This is a pattern that we see used in a number of places in the .NET framework, such as for Tuple.
You can use Tuple<T1,T2,T3> instead of anonymous class:
var items = db.bar.AsEnumerable().Select(c=>Tuple.Create(i.Prop1, i.Prop2, i.Prop3));
ProcessData(items,
new DataSelector<Tuple<T1,T2,T3>>("head1", d => d.Prop1.ToString()),
new DataSelector<Tuple<T1,T2,T3>>("head2", d => d.Prop2.ToString()));
private class DataSelector<T>
{
public DataSelector(string header, Func<T, string> selector)
{
Header = header;
Selector = selector;
}
public string Header { get; set; }
public Func<T, string> Selector { get; set; }
}
private static void Process<T>(IEnumerable<T> stuff,
params ColumnDef<T>[] defs)
{
foreach (var item in stuff) {
// Use all defs like...
Console.WriteLine(defs[0].Header + ": " + defs[0].Selector(item));
}
}
I want to require things which implement an interface (or derive from a class) to have an implementation for Aggregate included. That is, if they are of type T I want them to have something of type Func<T,T,T>. In Haskell this is called a "monoid".
EDIT: What I want to call is something like this:
list.Aggregate((x, accum) => accump.MAppend(x));
Based on DigalD's answer, this is my best attempt, but it doesn't compile:
interface IMonoid<T>
{
T MAppend(T other);
}
class Test
{
public static void runTest<T>(IEnumerable<IMonoid<T>> list)
{
// doesn't work
list.Aggregate((x, ac) => ac.MAppend(x));
}
}
A monoid is an associative operation together with an identity for that operation.
interface Monoid<T> {
T MAppend(T t1, T t2);
T MEmpty
}
The contract of a monoid is that for all a, b, and c:
Associativity: MAppend(Mappend(a, b), c) = MAppend(a, Mappend(b, c))
Left identity: MAppend(MEmpty, a) = a
Right identity: MAppend(a, MEmpty) = a
You can use it to add up the elements in a list:
class Test {
public static T runTest<T>(IEnumerable<T> list, Monoid<T> m) {
list.Aggregate(m.MEmpty, (a, b) => m.MAppend(a, b));
}
}
The answer by Apocalisp looks closest to the mark, but I'd prefer something like this:
public interface IMonoid<T>
{
T Combine(T x, T y);
T Identity { get; }
}
While Haskell calls the monoid identity mempty, I think it's more reasonable to use the language of abstract algebra, so I named the identity value Identity. Likewise, I prefer the term Combine over Haskell's mappend, because the word append seems to indicate some sort of list append operation, which it doesn't have to be at all. Combine, however, isn't a perfect word either, because neither the first nor the last monoids combine the values; instead, they ignore one of them. I'm open to suggestions of a better name for the binary operation...
(In Haskell, BTW, I prefer using the <> operator alias instead of the mappend function, so that sort of side-steps the naming issue...)
Using the above IMonoid<T> interface, you can now write an extension method like this:
public static class Monoid
{
public static T Concat<T>(this IMonoid<T> m, IEnumerable<T> values)
{
return values.Aggregate(m.Identity, (acc, x) => m.Combine(acc, x));
}
}
Here, I completely arbitrarily and inconsistently decided to go with Haskell's naming, so I named the method Concat.
As I describe in my article Monoids accumulate, one always has to start the accumulation with the monoidal identity, in this case m.Identity.
As I describe in my article Semigroups accumulate, instead of an imperative for loop, you can use the Aggregate extension method, but you'll have to use the overload that takes an initial seed value. That seed value is m.Identity.
You can now define various monoids, such as Sum:
public class Sum : IMonoid<int>
{
public int Combine(int x, int y)
{
return x + y;
}
public int Identity
{
get { return 0; }
}
}
or Product:
public class Product : IMonoid<int>
{
public int Combine(int x, int y)
{
return x * y;
}
public int Identity
{
get { return 1; }
}
}
Since I made the monoid argument the this argument of the Concat method, the method extends the IMonoid<T> interface, rather than IEnumerable<T>. I think this gives you a more readable API. For example:
var s = new Sum().Concat(new[] { 1000, 300, 30, 7 });
produces s == 1337, while
var p = new Product().Concat(new[] { 2, 3, 7 });
produces p == 42.
If you don't like having to create a new Sum() or new Product() object every time, you can make your monoids Singletons, like this All monoid:
public class All : IMonoid<bool>
{
public static All Instance = new All();
private All() { }
public bool Combine(bool x, bool y)
{
return x && y;
}
public bool Identity
{
get { return true; }
}
}
which you can use like this:
var a = All.Instance.Concat(new[] { true, true, true });
Here, a is true. You can use a similarly written Any monoid in the same way:
var a = Any.Instance.Concat(new[] { false, true, false });
I'll leave it as an exercise for the reader to figure out how Any is implemented.
What about this version:
interface IMonoid<T>
{
T MAppend(IMonoid<T> other);
}
class Test
{
public static void runTest<T>(IEnumerable<IMonoid<T>> list)
where T : IMonoid<T>
{
list.Aggregate((x, ac) => ac.MAppend(x));
}
}
Or better yet, enforcing it from the start:
interface IMonoid<T>
where T : IMonoid<T>
{
T MAppend(IMonoid<T> other);
}
Shouldn't you just make the Interface generic as well?
interface IMonoid<T>
{
public IMonoidHandler<T> handler {get;set;}
}
Just a little niggle about LINQ syntax. I'm flattening an IEnumerable<IEnumerable<T>> with SelectMany(x => x).
My problem is with the lambda expression x => x. It looks a bit ugly. Is there some static 'identity function' object that I can use instead of x => x? Something like SelectMany(IdentityFunction)?
Unless I misunderstand the question, the following seems to work fine for me in C# 4:
public static class Defines
{
public static T Identity<T>(T pValue)
{
return pValue;
}
...
You can then do the following in your example:
var result =
enumerableOfEnumerables
.SelectMany(Defines.Identity);
As well as use Defines.Identity anywhere you would use a lambda that looks like x => x.
Note: this answer was correct for C# 3, but at some point (C# 4? C# 5?) type inference improved so that the IdentityFunction method shown below can be used easily.
No, there isn't. It would have to be generic, to start with:
public static Func<T, T> IdentityFunction<T>()
{
return x => x;
}
But then type inference wouldn't work, so you'd have to do:
SelectMany(Helpers.IdentityFunction<Foo>())
which is a lot uglier than x => x.
Another possibility is that you wrap this in an extension method:
public static IEnumerable<T> Flatten<T>
(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(x => x);
}
Unfortunately with generic variance the way it is, that may well fall foul of various cases in C# 3... it wouldn't be applicable to List<List<string>> for example. You could make it more generic:
public static IEnumerable<TElement> Flatten<TElement, TWrapper>
(this IEnumerable<TWrapper> source) where TWrapper : IEnumerable<TElement>
{
return source.SelectMany(x => x);
}
But again, you've then got type inference problems, I suspect...
EDIT: To respond to the comments... yes, C# 4 makes this easier. Or rather, it makes the first Flatten method more useful than it is in C# 3. Here's an example which works in C# 4, but doesn't work in C# 3 because the compiler can't convert from List<List<string>> to IEnumerable<IEnumerable<string>>:
using System;
using System.Collections.Generic;
using System.Linq;
public static class Extensions
{
public static IEnumerable<T> Flatten<T>
(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(x => x);
}
}
class Test
{
static void Main()
{
List<List<string>> strings = new List<List<string>>
{
new List<string> { "x", "y", "z" },
new List<string> { "0", "1", "2" }
};
foreach (string x in strings.Flatten())
{
Console.WriteLine(x);
}
}
}
With C# 6.0 and if you reference FSharp.Core you can do:
using static Microsoft.FSharp.Core.Operators
And then you're free to do:
SelectMany(Identity)
With C# 6.0 things are getting better. We can define the identity function in the way suggested by #Sahuagin:
static class Functions
{
public static T It<T>(T item) => item;
}
And then use it in SelectMany the using static constructor:
using Functions;
...
var result = enumerableOfEnumerables.SelectMany(It);
I think it looks very laconic in the such way. I also find the identity function useful when building dictionaries:
class P
{
P(int id, string name) // Sad. We are not getting primary constructors in C# 6.0
{
ID = id;
Name = id;
}
int ID { get; }
int Name { get; }
static void Main(string[] args)
{
var items = new[] { new P(1, "Jack"), new P(2, "Jill"), new P(3, "Peter") };
var dict = items.ToDictionary(x => x.ID, It);
}
}
This may work in the way you want. I realize Jon posted a version of this solution, but he has a second type parameter which is only necessary if the resulting sequence type is different from the source sequence type.
public static IEnumerable<T> Flatten<T>(this IEnumerable<T> source)
where T : IEnumerable<T>
{
return source.SelectMany(item => item);
}
You can get close to what you need. Instead of a regular static function, consider an extension method for your IEnumerable<T>, as if the identity function is of the collection, not the type (a collection can generate the identity function of its items):
public static Func<T, T> IdentityFunction<T>(this IEnumerable<T> enumerable)
{
return x => x;
}
with this, you don't have to specify the type again, and write:
IEnumerable<IEnumerable<T>> deepList = ... ;
var flat = deepList.SelectMany(deepList.IdentityFunction());
This does feel a bit abusive though, and I'd probably go with x=>x. Also, you cannot use it fluently (in chaining), so it will not always be useful.
I'd go with a simple class with a single static property and add as many as required down the line
internal class IdentityFunction<TSource>
{
public static Func<TSource, TSource> Instance
{
get { return x => x; }
}
}
SelectMany(IdentityFunction<Foo>.Instance)