-2

I understand I cannot modify default(T).

How to change what default(T) returns in C#?

In my situation, we have several classes that implement functionality of the base class:

T RequestForData<T>(string request)
{
    return default(T);
}

I need to modify this default functionality to handle a "Refresh" call, which I can write like this:

private DataContext _dc;

T RequestForData<T>(string request)
{
  if (request == "Refresh")
  {
    if ((_dc != null) && !_dc.HasPendingChanges())
    {
      _dc.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues);
    }
  }
  return default(T);
}

These can now be called from the MDI parent form:

foreach (var form in this.Forms)
{
    form.RequestForData<bool>("Refresh");
}

As you can see from the way I have called it, RequestForData returns a Boolean value.

If I handle the call in one of my forms, I want to return TRUE, but this returns an error in Visual Studio.

Cannot implicitly convert type 'bool' to 'T'

screenshot

FYI: I tried a cast, too, but the compiler says that is redundant.

How do I handle returning a value type as specified by ?

Community
  • 1
  • 1
  • 3
    What would you expect to happen if someone had called `RequestForData` and you'd tried to return `true`? – Jon Skeet Sep 22 '16 at 16:22
  • 1
    Once I used a hack `(T)(dynamic)true`. Assuming value can be converted, the code will execute fine. Otherwise you'll get runtime error instead of compilation error, if that's what you need to get and you are sure nobody will call your method with string generic argument. – Sasha Sep 22 '16 at 16:24
  • @JonSkeet - Not sure. Another developer wrote this, and it has never been used for anything. Would I need to box the Boolean value and cast it back to T? `return (T)(Object)true;` –  Sep 22 '16 at 16:25
  • 3
    @jp2code: That would work, *if* `T` is `bool` (or `ValueType`, or `object`). But perhaps the method should really just return `bool` instead of being generic? It doesn't look like it's doing anything useful with `T`... – Jon Skeet Sep 22 '16 at 16:25
  • 3
    What is the point of the return value if you only ever return `default(T)`? There's no meaningful way to return an arbitrary value of `T` so either make it `object` and make the callee cast or change the return type to `void`. – Lee Sep 22 '16 at 16:26
  • @OleksandrPshenychnyy = that compiles just fine! –  Sep 22 '16 at 16:32
  • Why is your method for refreshing a generic method that takes a string, and not just `bool Refresh()`? – Harrison Paine Sep 22 '16 at 16:39
  • @HarrisonPaine - the developer that wrote the original design wanted it to be as flexible as possible, I guess. –  Sep 22 '16 at 16:44
  • 1
    The design is, frankly, bizarre, not flexible. 1. Generic method means you need to know the *exact* parameter, i.e. return type, so no loose coupling and no "flexibility". 2. Default value is supposed to have a "special meaning" (like returning `0` for an `int` is somehow special). If returning `null` instead of throwing is bad, this is ridiculously bad. 3. Apart from passing a type parameter (which is an OOP anti-pattern), the parameter is, on top of that, a `string`, opening the door even further to runtime errors. Now you need to pass the *exact* hardcoded combination of type+string value. – vgru Sep 22 '16 at 16:57

4 Answers4

1

Perhaps you could use a Nullable<bool>:

var result = form.RequestForData<bool?>("Refresh") ?? true;

However, I don't see the point in your generic method returning a value at all. Why not just make it a void method? What's the information that this return value carries?

vgru
  • 49,838
  • 16
  • 120
  • 201
1

Assuming you are sure nobody will use your method with, let's say string generic argument, you could avoid the compiler error by doing the following:

return (T)(dynamic)true;

Of course it will lead to runtime error in case bool can't be cast to T. But for me such solution worked pretty well once while implementing typed data-reader from SQL-DataTable.

PS: But still I don't believe this hack is justified for this particular method. It's really primitive and can't return anything other then boolean, can't work with any other generic argument. So you better either make it return bool, or void as was suggested in other comments.

Sasha
  • 8,537
  • 4
  • 49
  • 76
  • This is exactly what I am using for the moment, so it solves my immediate problem. Still, I do not understand how any developer would otherwise return something other than the default. –  Sep 22 '16 at 16:48
  • 1
    @jp2code: You are looking at this problem from the wrong perspective, the issue you are having is here because the code is very poorly designed. – vgru Sep 22 '16 at 17:02
1

The question got a downvote.

I think people on here vote it down when they think they know everything and there is no way they can see to solve the problem.

Here is how we resolved the coding dilemma:

T RequestForData<T>(string request)
{
  if (request == "Refresh")
  {
    if ((_dc != null) && !_dc.HasPendingChanges())
    {
      _dc.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues);
      return (T)Convert.ChangeType(true, typeof(T));
    }
  }
  return default(T);
}

If anyone sees why that will not work, feel free to comment.

  • It will work, there so no doubt. And then you'll have `RequestForData("Refresh")` somewhere in your code, and it will fail at runtime. Now ask yourself, what possible problem does this method solve that couldn't be solved better with a parameterless non-generic method which returns a `bool` value? Like `bool RequestRefresh();`? Instead of letting compiler warn you if you make a mistake, you effectively want to put several methods into one method, and use a combination of a `T` type and a `string` to decide how it will work, so that the compiler cannot possibly detect the error. – vgru Sep 22 '16 at 19:19
  • @Groo, the designer of this form defended his design with, "The person calling is going to get back what they are calling." He wanted this "to be as generic as possible" so that he did not have to write a different return type for each scenario in his Document Manager. –  Sep 23 '16 at 16:37
-3

try this implementation may work :

bool RequestForData<T>(string request)
{
    return true;
}

or in a more flexible form :

object RequestForData<T>(string request)
{
     if(conditionOk)    
         return default(T);
     else
         return false;
}
Saeid
  • 4,147
  • 7
  • 27
  • 43