简体   繁体   中英

How to promise the compiler that the generic type will have a certain property?

I'd like to use a certain operation for multiple variable types (both native and objects) so I'm using the generic return type as follows.

private Generic Field<Generic>(String field)
{
  if (BagOfJunk.Properties.Contains(field))
    return (Generic)BagOfJunk[field];
  return default(Generic);
}

This works well (and BagOfJunk is just a property of this from which I'm pulling out Object typed values). Now, during run-time, when a field isn't contained in the bag, I get the default value to be null . Hence, in the code, I need to perform a check as follows.

NumericType protoNumber = Field<NumericType>("beep");
int number = protoNumber != null ? protoNumber.Value : -1;

DateType protoDate = Field<DateType>("boop");
DateTime date = protoDate != null ? protoDate.Value : null;

I'd like to make the code more compact, so I tried to design a method that does the above four lines in one swoop, for a generic type. The result is below but, of course, it doesn't compile, because the type GenericIn isn't specific enough to have a property Value .

private GenericOut Field<GenericIn, GenericOut>(String field)
{
  GenericIn input = Field<GenericIn>(field);
  if (input != null)
    return (GenericOut)input.Value;
  return default(GenericOut);
}

How can I ensure the computer that my GenericIn isn't general - by promising that whatever stuff I'll shove into it, it'll always have the property Value in it?

Edit

It should be emphasized that the type of Value needs to be generic ( equivalent to GenericOut ). I noticed that I didn't stress that strongly enough. So the interface that can be used need to declare a property of general type like the following.

interface ObjectWithValue { public Generic Value { get; } }

You can use an interface and apply a where constraint on the type to implement that interface, like below:

interface IHasPropertyValue<TValue> {
  TValue Value { get; }
}

class MyType {
  public TValue Method<T, TValue>(T obj) where T : IHasPropertyValue<TValue> {
    return obj.Value;
  }
}

EDIT: Modified the code above to make it more specific to the comment asked below.

put that property in an interface (or a class) and use the generic constraint "where":

public interface IMyInterface
{
    public object Value { get; set; }
}

public class C<T> where T:IMyInterface

To build upon the answers so far, you need to create an interface that will be implemented by your GenericIn that will both guarantee that it has a property Value and that the property is of type GenericOut .

interface IHasValue<TOut>
{
    TOut Value { get; }
}

private TOut Field<TIn, TOut>(string field) where TIn : IHasValue<TOut>
{
    var input = Field<TIn>(field);
    return input == null ? default(TOut) : input.Value;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM