1

I have previously created methods that take a property as input using the following syntax:

public void MyMethod<T>(Expression<Func<T>> property) { }

public int MyProperty { get; set; }

public void SomeOtherMethod() {
    MyMethod(() => MyProperty);
}

That way I can, for example, cast the property to a MemberExpression and get the fully qualified name of the property.

However, is it possible to do the same in a class constructor, or have a property that stores another property, like how the property variable does in MyMethod()?

I have tried the following, but that didn't work because the type parameter is not specified in either cases, but I wouldn't even know which type to use... especially because the type is magically inferred in the topmost example.

In constructor

public class MyClass<T> {
    public MyClass(Expression<Func<T>> property) { }
}

public int MyProperty { get; set; }

var myClass = new MyClass(() => MyProperty);

As property

public class MyClass<T> {
    public Expression<Func<T>> SomeProperty { get; set; }
}

public int MyProperty { get; set; }

var myClass = new MyClass() { SomeProperty = () => MyProperty };

So, how can I have a property expression in a constructor or property of its own without having the use the type definition?

TheHvidsten
  • 4,028
  • 3
  • 29
  • 62

2 Answers2

1

Is it possible to [infer generic parameters] in a class constructor?

In C# generic inference is not supported on constructors, so you have to set it explicitly:

var myClass = new MyClass<int>(() => MyProperty);

The main reason it's not supported is because there are often many types that could be used as the generic constraint due to implicit type conversions, so the compiler would have to choose the "best" generic parameters based on the information that it has. The costs associated with designing, programming, testing, documenting, and integrating this logic outweigh the benefit, or at least don't provide a relative benefit that exceeds the other features that MS could spend time developing.

In this case you know the best generic parameter type because the MyProperty property returns an int. Technically you could use any type that is implicitly convertible from int (object, double, etc.) but int is the best fit.

Could I maybe use object as a catch-all?

Sure, but then your code isn't generic. You can just do

public class MyClass {
    public MyClass(Expression<Func<object>> property) { }
}
Community
  • 1
  • 1
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • That's a shame, because I was hoping to be able to use this syntax as a generic for all kinds of properties. The properties can be all kinds of types (string, int, double, custom classes). Could I maybe use `object` as a catch-all, because the type in itself isn't as interesting, but the `MemberExpression` of the property is? – TheHvidsten Jun 28 '16 at 12:56
  • It depends on what else `MyClass` _does_ with the generic type. If you're just going to use `object`, though, I don't see why you need generics at all. You can just do `public class MyClass { public MyClass(Expression> property) { } }` – D Stanley Jun 28 '16 at 12:59
  • For the specific use case I'm developing now, hardcoding the type to avoid generics will solve all my problems. I'm not holding my breath for MS to implement it in C#-47 ;) Thanks for the clarification! – TheHvidsten Jun 28 '16 at 13:20
0

You need to supply the type parameter of T

var myClass = new MyClass<int>(() => MyProperty);

var myClass = new MyClass<int>() { SomeProperty = () => MyProperty };

Otherwise it won't know what type of expression it should get in the constructor.

James Jenkinson
  • 1,563
  • 2
  • 16
  • 33