简体   繁体   中英

Generic return type in C#

Was practicing Generics. Consider a stack method below. What is the best way of doing error checking other than throwing exceptions in a generic method. What if I want to return some result in this method.

public T pop()
{
    if (top >= 0)
        return arr[top--];
    return -1 or null;
}

The only thing you could do is return default(T) , which is the default value for the type T ( null for reference types, zero for integral types and zeroed-fields object for other value types). However, this is generally a bad idea as you'll have no way to distinguish between a 0 that was popped or a 0 that indicates an error. Exceptions are generally the best way to go in such cases, but you could also change your method as follows:

public bool TryPop(out T value)
{
    if (top >= 0)
    {
        value = arr[top--];
        return true;
    }
    value = default(T);
    return false;
}

您可以return default(T) ,它将返回0个初始化值类型(例如,所有数值类型将初始化为0),并且null为引用类型。

I came here in search of a solution to a slightly different issue, involving a static method that takes two generic arrays and returns a new generic array. Since my method was static, I couldn't use the example, except as inspiration. Instead, I developed the following solution.

T [ ] raMerged = ( T [ ] ) alMerged.ToArray ( typeof ( T ) );
return raMerged;

In the above snippet, alMerged is an ArrayList of generic objects T.

This satisfies the conditions of the contract specified by the method signature, which is as follows.

public static T [ ] MergeNewItemsIntoArray<T> (
T [ ] paMasterList ,
T [ ] paNewItems )
where T : IComparable , new ( )

In the signature, the where clause illustrates my resolution of another issue that I found in several threads, none of which directly addressed this question. Nevertheless, hopefully, this will help at least one other soul.

It seems like your question really has two parts

The first part being how to provide a default value if one is not available. As other people have pointed out the C# expression default(T) will work for this scenario. It returns null for reference types and 0 initialized values for structs.

The second part being what is the best way to handle the error case other than to throw an exception. Collection APIs tend to use the TryXXX pattern for this type of scenario

bool TryPop(out T value) { 
  if ( top >= 0 ) {
    value = arr[top--];
    return true;
  }
  value = default(T);
  return false;
}

Your question is unclear. Error checking can be done the same ways as always - catching exceptions. Raising errors should generally be done by throwing exceptions. That is what they're for, after all.

If you want to return null you can do that, but then you have to make sure that type T is a class, not a struct, like so:

public T pop()
    where T: class
{
     ...
}

If you want to be able to return null when the stack is empty you can try something like this:

class GenericStack<T>
{
    T[] arr;
    int top;

    public T pop()
    {
        if (top >= 0)
            return arr[top--];
        return default(T);
    }
}

And then you can use use like this:

        var stack = new GenericStack<int?>();

        var res = stack.pop(); // res will be null

Notice the stack object is of type int? so we can return nulls.

Direct approach (use generics and return value or null)

class DemoClass<T> where T : struct
{
   public T? PopValueOrNull() 
   { 
     if ( this._top >= 0 ) { 
        return this._arr[this._top--];
      } 

      return null; 
    }
}

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